/* * This module started out as the core of Peter Shannon's "Python * OpenSSL Wrappers" package, an excellent but somewhat dated package * which I encountered while looking for some halfway sane way to cram * RFC 3779 certificate support code into Python. * * At this point enough of the code has been added or rewritten that * it's unclear (either way) whether this code properly qualifies as a * derivative work. Given that both Peter's original code and all of * subsequent changes to it were done under something equivalent to a * BSD license, this may not matter very much, but the following * attempts to give proper credit to all concerned. * **** * * Copyright (C) 2014 Dragon Research Labs ("DRL") * Portions copyright (C) 2009--2013 Internet Systems Consortium ("ISC") * Portions copyright (C) 2006--2008 American Registry for Internet Numbers ("ARIN") * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notices and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND DRL, ISC, AND ARIN DISCLAIM ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DRL, * ISC, OR ARIN BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * **** * * Portions Copyright (c) 2001, 2002, Peter Shannon * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * * The name of the contributors may be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* $Id$ */ #define PY_SSIZE_T_CLEAN 1 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * GCC attribute to let us tell GCC not to whine about unused formal * parameters when we're in maximal warning mode. */ #ifdef __GNUC__ #define GCC_UNUSED __attribute__((unused)) #else define GCC_UNUSED #endif /* * Maximum size of a raw IP (v4 or v6) address, in bytes. */ #define RAW_IPADDR_BUFLEN 16 /* * Maximum size of an ASN.1 Integer converted from a Python Long, in bytes. */ #define MAX_ASN1_INTEGER_LEN 20 /* Digests */ #define MD5_DIGEST 2 #define SHA_DIGEST 3 #define SHA1_DIGEST 4 #define SHA256_DIGEST 6 #define SHA384_DIGEST 7 #define SHA512_DIGEST 8 /* Object format */ #define SHORTNAME_FORMAT 1 #define LONGNAME_FORMAT 2 #define OIDNAME_FORMAT 3 /* AsymmetricParam EC curves */ #define EC_P256_CURVE NID_X9_62_prime256v1 /* Object check functions */ #define POW_X509_Check(op) PyObject_TypeCheck(op, &POW_X509_Type) #define POW_X509Store_Check(op) PyObject_TypeCheck(op, &POW_X509Store_Type) #define POW_X509StoreCTX_Check(op) PyObject_TypeCheck(op, &POW_X509StoreCTX_Type) #define POW_CRL_Check(op) PyObject_TypeCheck(op, &POW_CRL_Type) #define POW_Asymmetric_Check(op) PyObject_TypeCheck(op, &POW_Asymmetric_Type) #define POW_AsymmetricParams_Check(op) PyObject_TypeCheck(op, &POW_AsymmetricParams_Type) #define POW_Digest_Check(op) PyObject_TypeCheck(op, &POW_Digest_Type) #define POW_CMS_Check(op) PyObject_TypeCheck(op, &POW_CMS_Type) #define POW_IPAddress_Check(op) PyObject_TypeCheck(op, &POW_IPAddress_Type) #define POW_ROA_Check(op) PyObject_TypeCheck(op, &POW_ROA_Type) #define POW_Manifest_Check(op) PyObject_TypeCheck(op, &POW_Manifest_Type) #define POW_ROA_Check(op) PyObject_TypeCheck(op, &POW_ROA_Type) static char pow_module__doc__ [] = "Python interface to RFC-3779-enabled OpenSSL. This code is intended\n" "to support the rpki.net toolset.\n" "\n" "This code started out life as Peter Shannon's excellent \"Python OpenSSL\n" "Wrappers\" package. It has been extensively modified since then, to add\n" "support for things needed for the RPKI protocols, to upgrade the code\n" "to use modern (circa Python 2.7) classes, and to remove code not\n" "needed for RPKI work.\n" ; /* * Handle NIDs we wish OpenSSL knew about. This is carefully (we * hope) written to do nothing at all for any NID that OpenSSL knows * about; the intent is just to add definitions for things OpenSSL * doesn't know about yet. Of necessity, this is a bit gross, since * it confounds runtime static variables with predefined macro names, * but we try to put all the magic associated with this in one place. */ #ifndef NID_rpkiManifest static int NID_rpkiManifest; #endif #ifndef NID_signedObject static int NID_signedObject; #endif #ifndef NID_rpkiNotify static int NID_rpkiNotify; #endif static const struct { int *nid; const char *oid; const char *sn; const char *ln; } missing_nids[] = { #ifndef NID_rpkiManifest {&NID_rpkiManifest, "1.3.6.1.5.5.7.48.10", "id-ad-rpkiManifest", "RPKI Manifest"}, #endif #ifndef NID_signedObject {&NID_signedObject, "1.3.6.1.5.5.7.48.11", "id-ad-signedObject", "Signed Object"}, #endif #ifndef NID_rpkiNotify {&NID_rpkiNotify, "1.3.6.1.5.5.7.48.13", "id-ad-rpkiNotify", "RPKI RRDP Notification"}, #endif }; /* * IP versions. */ typedef struct ipaddress_version { unsigned version; unsigned afi; unsigned af; unsigned length; } ipaddress_version; static const ipaddress_version ipaddress_version_4 = { 4, IANA_AFI_IPV4, AF_INET, 4 }; static const ipaddress_version ipaddress_version_6 = { 6, IANA_AFI_IPV6, AF_INET6, 16 }; static const ipaddress_version * const ipaddress_versions[] = { &ipaddress_version_4, &ipaddress_version_6 }; /* * Names of bits in the KeyUsage BitString (RFC 5280 4.2.1.3). */ static const char * const key_usage_bit_names[] = { "digitalSignature", /* (0) */ "nonRepudiation", /* (1) */ "keyEncipherment", /* (2) */ "dataEncipherment", /* (3) */ "keyAgreement", /* (4) */ "keyCertSign", /* (5) */ "cRLSign", /* (6) */ "encipherOnly", /* (7) */ "decipherOnly", /* (8) */ NULL }; /* * Exception objects. */ static PyObject *ErrorObject, *OpenSSLErrorObject, *POWErrorObject, *NotVerifiedErrorObject; /* * Constructor for customized datetime class. */ static PyObject *custom_datetime; /* * "ex_data" index for pointer we want to attach to X509_STORE_CTX so * we can extract it in callbacks. */ static int x509_store_ctx_ex_data_idx = -1; /* * Declarations of type objects (definitions come later). */ static PyTypeObject POW_X509_Type, POW_X509Store_Type, POW_X509StoreCTX_Type, POW_CRL_Type, POW_Asymmetric_Type, POW_AsymmetricParams_Type, POW_Digest_Type, POW_CMS_Type, POW_IPAddress_Type, POW_ROA_Type, POW_Manifest_Type, POW_ROA_Type, POW_PKCS10_Type; /* * Object internals. */ typedef struct { PyObject_HEAD unsigned char address[16]; const struct ipaddress_version *type; } ipaddress_object; typedef struct { PyObject_HEAD X509 *x509; } x509_object; typedef struct { PyObject_HEAD X509_STORE *store; PyObject *ctxclass; } x509_store_object; typedef struct { PyObject_HEAD X509_STORE_CTX *ctx; x509_store_object *store; } x509_store_ctx_object; typedef struct { PyObject_HEAD X509_CRL *crl; } crl_object; typedef struct { PyObject_HEAD EVP_PKEY *pkey; } asymmetric_object; typedef struct { PyObject_HEAD EVP_PKEY *pkey; } asymmetric_params_object; typedef struct { PyObject_HEAD EVP_MD_CTX digest_ctx; int digest_type; } digest_object; typedef struct { PyObject_HEAD CMS_ContentInfo *cms; } cms_object; typedef struct { cms_object cms; /* Subclass of CMS */ ROA *roa; } roa_object; typedef struct { cms_object cms; /* Subclass of CMS */ Manifest *manifest; } manifest_object; typedef struct { PyObject_HEAD X509_REQ *pkcs10; X509_EXTENSIONS *exts; } pkcs10_object; /* * Utility functions. */ /* * Minimal intervention debug-by-printf() hack, use only for good. */ #if 0 #define KVETCH(_msg_) write(2, _msg_ "\n", sizeof(_msg_)) #else #define KVETCH(_msg_) ((void) 0) #endif #if 0 #define ENTERING(_name_) KVETCH("Entering " #_name_ "()") #else #define ENTERING(_name_) ((void) 0) #endif /* * Error handling macros. All of macros assume that there's a cleanup * label named "error" which these macros can use as a goto target. */ #define lose(_msg_) \ do { \ PyErr_SetString(POWErrorObject, (_msg_)); \ goto error; \ } while (0) #define lose_no_memory() \ do { \ PyErr_NoMemory(); \ goto error; \ } while (0) #define lose_type_error(_msg_) \ do { \ PyErr_SetString(PyExc_TypeError, (_msg_)); \ goto error; \ } while (0) #define lose_value_error(_msg_) \ do { \ PyErr_SetString(PyExc_ValueError, (_msg_)); \ goto error; \ } while (0) #define lose_openssl_error(_msg_) \ do { \ set_openssl_exception(OpenSSLErrorObject, (_msg_), 0); \ goto error; \ } while (0) #define lose_not_verified(_msg_) \ do { \ PyErr_SetString(NotVerifiedErrorObject, (_msg_)); \ goto error; \ } while (0) #define assert_no_unhandled_openssl_errors() \ do { \ if (ERR_peek_error()) { \ set_openssl_exception(OpenSSLErrorObject, NULL, __LINE__); \ goto error; \ } \ } while (0) #define POW_assert(_cond_) \ do { \ if (!(_cond_)) { \ (void) PyErr_Format(POWErrorObject, \ "Assertion %s failed at " __FILE__ ":%d", \ #_cond_, __LINE__); \ goto error; \ } \ } while (0) /* * Consolidate some tedious EVP-related switch statements. */ static const EVP_MD * evp_digest_factory(int digest_type) { switch (digest_type) { case MD5_DIGEST: return EVP_md5(); case SHA_DIGEST: return EVP_sha(); case SHA1_DIGEST: return EVP_sha1(); case SHA256_DIGEST: return EVP_sha256(); case SHA384_DIGEST: return EVP_sha384(); case SHA512_DIGEST: return EVP_sha512(); default: return NULL; } } /* * Raise an exception with data pulled from the OpenSSL error stack. * Exception value is a tuple with some internal structure. * * If a string error message is supplied, that string is the first * element of the exception value tuple. * * If a non-zero line number is supplied, a string listing this as an * unhandled exception detected at that line will be the next element * of the exception value tuple (or the first, if no error message was * supplied). * * Remainder of exception value tuple is zero or more tuples, each * representing one error from the stack. * * Each error tuple contains six slots: * - the numeric error code * - string translation of numeric error code ("reason") * - name of library in which error occurred * - name of function in which error occurred * - name of file in which error occurred * - line number in file where error occurred */ static void set_openssl_exception(PyObject *error_class, const char *msg, const int unhandled_line) { PyObject *errtuple = NULL; PyObject *errlist = NULL; unsigned long err; const char *file; int line; if ((errlist = PyList_New(0)) == NULL) return; if (msg) { PyObject *s = PyString_FromString(msg); (void) PyList_Append(errlist, s); Py_XDECREF(s); } if (unhandled_line) { PyObject *s = PyString_FromFormat("Unhandled OpenSSL error at " __FILE__ ":%d!", unhandled_line); (void) PyList_Append(errlist, s); Py_XDECREF(s); } while ((err = ERR_get_error_line(&file, &line)) != 0) { PyObject *t = Py_BuildValue("(issssi)", err, ERR_reason_error_string(err), ERR_lib_error_string(err), ERR_func_error_string(err), file, line); (void) PyList_Append(errlist, t); Py_XDECREF(t); } if ((errtuple = PyList_AsTuple(errlist)) != NULL) PyErr_SetObject(error_class, errtuple); Py_XDECREF(errtuple); Py_XDECREF(errlist); } static X509_NAME * x509_object_helper_set_name(PyObject *dn_obj) { PyObject *rdn_obj = NULL; PyObject *pair_obj = NULL; PyObject *type_obj = NULL; PyObject *value_obj = NULL; X509_NAME *name = NULL; char *type_str, *value_str; int asn1_type, i, j; if ((name = X509_NAME_new()) == NULL) lose_no_memory(); for (i = 0; i < PySequence_Size(dn_obj); i++) { if ((rdn_obj = PySequence_GetItem(dn_obj, i)) == NULL) goto error; if (!PySequence_Check(rdn_obj) || PySequence_Size(rdn_obj) == 0) lose_type_error("each RDN must be a sequence with at least one element"); for (j = 0; j < PySequence_Size(rdn_obj); j++) { if ((pair_obj = PySequence_GetItem(rdn_obj, j)) == NULL) goto error; if (!PySequence_Check(pair_obj) || PySequence_Size(pair_obj) != 2) lose_type_error("each name entry must be a two-element sequence"); if ((type_obj = PySequence_GetItem(pair_obj, 0)) == NULL || (type_str = PyString_AsString(type_obj)) == NULL || (value_obj = PySequence_GetItem(pair_obj, 1)) == NULL || (value_str = PyString_AsString(value_obj)) == NULL) goto error; if ((asn1_type = ASN1_PRINTABLE_type((unsigned char *) value_str, -1)) != V_ASN1_PRINTABLESTRING) asn1_type = V_ASN1_UTF8STRING; if (!X509_NAME_add_entry_by_txt(name, type_str, asn1_type, (unsigned char *) value_str, strlen((char *) value_str), -1, (j ? -1 : 0))) lose("Unable to add name entry"); Py_XDECREF(pair_obj); Py_XDECREF(type_obj); Py_XDECREF(value_obj); pair_obj = type_obj = value_obj = NULL; } Py_XDECREF(rdn_obj); rdn_obj = NULL; } return name; error: X509_NAME_free(name); Py_XDECREF(rdn_obj); Py_XDECREF(pair_obj); Py_XDECREF(type_obj); Py_XDECREF(value_obj); return NULL; } static PyObject * x509_object_helper_get_name(X509_NAME *name, int format) { X509_NAME_ENTRY *entry = NULL; PyObject *result = NULL; PyObject *rdn = NULL; PyObject *item = NULL; const char *oid = NULL; char oidbuf[512]; int i, set = -1; /* * Overall theory here: multi-value RDNs are very rare in the wild. * We should support them, so we don't throw an exception if handed * one in a BPKI certificate, but with minimal effort. What we care * about here is optimizing for the common case of single-valued RDNs. */ if ((result = PyTuple_New(X509_NAME_entry_count(name))) == NULL) goto error; for (i = 0; i < X509_NAME_entry_count(name); i++) { if ((entry = X509_NAME_get_entry(name, i)) == NULL) lose("Couldn't get certificate name"); if (entry->set < 0 || entry->set < set || entry->set > set + 1) lose("X509_NAME->set value out of expected range"); switch (format) { case SHORTNAME_FORMAT: oid = OBJ_nid2sn(OBJ_obj2nid(entry->object)); break; case LONGNAME_FORMAT: oid = OBJ_nid2ln(OBJ_obj2nid(entry->object)); break; case OIDNAME_FORMAT: oid = NULL; break; default: lose("Unknown name format"); } if (oid == NULL) { if (OBJ_obj2txt(oidbuf, sizeof(oidbuf), entry->object, 1) <= 0) lose_openssl_error("Couldn't translate OID"); oid = oidbuf; } if (entry->set > set) { set++; if ((item = Py_BuildValue("((ss#))", oid, ASN1_STRING_data(entry->value), (Py_ssize_t) ASN1_STRING_length(entry->value))) == NULL) goto error; PyTuple_SET_ITEM(result, set, item); item = NULL; } else { if ((rdn = PyTuple_GetItem(result, set)) == NULL) goto error; (void) _PyTuple_Resize(&rdn, PyTuple_Size(rdn) + 1); PyTuple_SET_ITEM(result, set, rdn); if (rdn == NULL) goto error; if ((item = Py_BuildValue("(ss#)", oid, ASN1_STRING_data(entry->value), (Py_ssize_t) ASN1_STRING_length(entry->value))) == NULL) goto error; PyTuple_SetItem(rdn, PyTuple_Size(rdn) - 1, item); rdn = item = NULL; } } if (++set != PyTuple_Size(result)) { if (set < 0 || set > PyTuple_Size(result)) lose("Impossible set count for DN, something went horribly wrong"); _PyTuple_Resize(&result, set); } return result; error: Py_XDECREF(item); Py_XDECREF(result); return NULL; } static STACK_OF(X509) * x509_helper_iterable_to_stack(PyObject *iterable) { STACK_OF(X509) *stack = NULL; PyObject *iterator = NULL; PyObject *item = NULL; if ((stack = sk_X509_new_null()) == NULL) lose_no_memory(); if (iterable != Py_None) { if ((iterator = PyObject_GetIter(iterable)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if (!POW_X509_Check(item)) lose_type_error("Inapropriate type"); if (!sk_X509_push(stack, ((x509_object *) item)->x509)) lose("Couldn't add X509 object to stack"); Py_XDECREF(item); item = NULL; } } Py_XDECREF(iterator); return stack; error: Py_XDECREF(iterator); Py_XDECREF(item); sk_X509_free(stack); return NULL; } /* * Pull items off an OpenSSL STACK and put them into a Python tuple. * Assumes that handler is stealing the OpenSSL references to the * items in the STACK, so shifts consumed frames off the stack so that * the appropriate _pop_free() destructor can clean up on failures. * This is OK because all current uses of this function are processing * the result of OpenSSL xxx_get1_xxx() methods which we have to free * in any case. */ static x509_object *x509_object_new_helper(PyTypeObject *, X509 *); static crl_object *crl_object_new_helper (PyTypeObject *, X509_CRL *); static PyObject * stack_to_tuple_helper(_STACK *sk, PyObject *(*handler)(void *)) { PyObject *result = NULL; PyObject *obj = NULL; int i; if ((result = PyTuple_New(sk_num(sk))) == NULL) goto error; for (i = 0; sk_num(sk); i++) { if ((obj = handler(sk_value(sk, 0))) == NULL) goto error; sk_shift(sk); if (PyTuple_SetItem(result, i, obj) != 0) goto error; obj = NULL; } return result; error: Py_XDECREF(obj); return NULL; } static PyObject * stack_to_tuple_helper_get_x509(void *cert) { x509_object *obj; ENTERING(stack_to_tuple_helper_get_x509); if ((obj = x509_object_new_helper(NULL, cert)) == NULL) return NULL; return (PyObject *) obj; } static PyObject * stack_to_tuple_helper_get_crl(void *crl) { crl_object *obj; ENTERING(stack_to_tuple_helper_get_crl); if ((obj = crl_object_new_helper(NULL, crl)) == NULL) return NULL; return (PyObject *) obj; } /* * Time conversion functions. Obvious mapping into Python data types * is datetime, or, rather, our customized rpki.sundial.datetime. * * Unsuprisingly, it's easiest for us to map between GeneralizedTime * (as restricted by RFC 5280) and datetime. Conversion between * GeneralizedTime and UTCTime is handled automatically according to * the RFC 5280 rules for those ASN.1 types where it's required. */ static PyObject * ASN1_TIME_to_Python(ASN1_TIME *t) { ASN1_GENERALIZEDTIME *g = NULL; PyObject *result = NULL; int year, month, day, hour, minute, second; if ((g = ASN1_TIME_to_generalizedtime(t, NULL)) == NULL) lose_openssl_error("Couldn't convert ASN.1 TIME"); if (sscanf((char *) g->data, "%4d%2d%2d%2d%2d%2dZ", &year, &month, &day, &hour, &minute, &second) != 6) lose("Couldn't scan ASN.1 TIME value"); if (custom_datetime != NULL && custom_datetime != Py_None) result = PyObject_CallFunction(custom_datetime, "iiiiii", year, month, day, hour, minute, second); else result = PyDateTime_FromDateAndTime(year, month, day, hour, minute, second, 0); error: ASN1_GENERALIZEDTIME_free(g); return result; } static ASN1_TIME * Python_to_ASN1_TIME(PyObject *arg, const int object_requires_utctime) { char buf[sizeof("20010401123456Z") + 1]; ASN1_TIME *result = NULL; const char *s = NULL; int ok; if (PyDateTime_Check(arg)) { if (snprintf(buf, sizeof(buf), "%4d%02d%02d%02d%02d%02dZ", PyDateTime_GET_YEAR(arg), PyDateTime_GET_MONTH(arg), PyDateTime_GET_DAY(arg), PyDateTime_DATE_GET_HOUR(arg), PyDateTime_DATE_GET_MINUTE(arg), PyDateTime_DATE_GET_SECOND(arg)) >= (int) sizeof(buf)) lose("Internal error -- GeneralizedTime buffer too small"); s = buf; } if (s == NULL && (s = PyString_AsString(arg)) == NULL) goto error; if (strlen(s) < 10) lose_type_error("String is too short to parse as a valid ASN.1 TIME"); if ((result = ASN1_TIME_new()) == NULL) lose_no_memory(); if (object_requires_utctime && ((s[0] == '1' && s[1] == '9' && s[2] > '4') || (s[0] == '2' && s[1] == '0' && s[2] < '5'))) ok = ASN1_UTCTIME_set_string(result, s + 2); else ok = ASN1_GENERALIZEDTIME_set_string(result, s); if (ok) return result; error: ASN1_TIME_free(result); return NULL; } /* * Extract a Python string from a memory BIO. */ static PyObject * BIO_to_PyString_helper(BIO *bio) { char *ptr = NULL; Py_ssize_t len = 0; if ((len = BIO_get_mem_data(bio, &ptr)) == 0) lose_openssl_error("Unable to get BIO data"); return Py_BuildValue("s#", ptr, len); error: return NULL; } static PyObject * read_from_string_helper(PyObject *(*object_read_helper)(PyTypeObject *, BIO *), PyTypeObject *type, PyObject *args) { PyObject *result = NULL; char *src = NULL; BIO *bio = NULL; Py_ssize_t len = 0; if (!PyArg_ParseTuple(args, "s#", &src, &len)) goto error; if ((bio = BIO_new_mem_buf(src, len)) == NULL) lose_no_memory(); result = object_read_helper(type, bio); error: BIO_free(bio); return result; } static PyObject * read_from_file_helper(PyObject *(*object_read_helper)(PyTypeObject *, BIO *), PyTypeObject *type, PyObject *args) { const char *filename = NULL; PyObject *result = NULL; BIO *bio = NULL; if (!PyArg_ParseTuple(args, "s", &filename)) goto error; if ((bio = BIO_new_file(filename, "rb")) == NULL) lose_openssl_error("Could not open file"); result = object_read_helper(type, bio); error: BIO_free(bio); return result; } /* * Simplify entries in method definition tables. See the "Common * Object Structures" section of the API manual for available flags. */ #define Define_Method(__python_name__, __c_name__, __flags__) \ { #__python_name__, (PyCFunction) __c_name__, __flags__, __c_name__##__doc__ } #define Define_Class_Method(__python_name__, __c_name__, __flags__) \ Define_Method(__python_name__, __c_name__, (__flags__) | METH_CLASS) /* * Convert an ASN1_INTEGER into a Python integer or long. */ static PyObject * ASN1_INTEGER_to_PyLong(ASN1_INTEGER *arg) { PyObject *result = NULL; PyObject *obj = NULL; if ((obj = _PyLong_FromByteArray(ASN1_STRING_data(arg), ASN1_STRING_length(arg), 0, 0)) != NULL) result = PyNumber_Int(obj); Py_XDECREF(obj); return result; } /* * Convert a Python long to an ASN1_INTEGER. * This is just nasty, do not read on a full stomach. * * Maximum size of integer to be converted here is taken from RFC 5280 * 4.1.2.2, which sets a maximum of 20 octets for an X.509 certificate * serial number. * * In theory we could use _PyLong_NumBits() to determine the length of * the long before converting, and raise OverflowError if it's too big. * Hmm. */ static ASN1_INTEGER * PyLong_to_ASN1_INTEGER(PyObject *arg) { PyObject *obj = NULL; ASN1_INTEGER *a = NULL; unsigned char buf[MAX_ASN1_INTEGER_LEN]; size_t len; memset(buf, 0, sizeof(buf)); /* * Make sure argument is a PyLong small enough that its length (in * bits!) doesn't overflow a size_t (which is a mis-use of size_t, * but take that up with whoever wrote _PyLong_NumBits()...). */ if ((obj = PyNumber_Long(arg)) == NULL || (len = _PyLong_NumBits(obj)) == (size_t) -1) goto error; /* * Next make sure it's a non-negative integer small enough to fit in * our buffer. If we really thought we needed to support larger * integers we could allocate this dynamically, but we don't, so * it's not worth the overhead. * * Paranoia: We can't convert len to bytes yet, because that * requires rounding up and we don't know yet that we have enough * headroom to do that arithmetic without overflowing a size_t. */ if (_PyLong_Sign(obj) < 0 || (len / 8) + 1 > sizeof(buf)) { PyErr_SetObject(PyExc_OverflowError, obj); goto error; } /* * Now that we know we're dealing with a sane number of bits, * convert it to bytes. */ len = (len + 7) / 8; /* * Extract that many bytes. */ if (_PyLong_AsByteArray((PyLongObject *) obj, buf, len, 0, 0) < 0) goto error; /* * We're done with the PyLong now. */ Py_XDECREF(obj); obj = NULL; /* * Generate the ASN1_INTEGER and return it. */ if ((a = ASN1_INTEGER_new()) == NULL || (a->length < (int) len + 1 && (a->data = OPENSSL_realloc(a->data, len + 1)) == NULL)) lose_no_memory(); a->type = V_ASN1_INTEGER; a->length = len; a->data[len] = 0; memcpy(a->data, buf, len); return a; error: Py_XDECREF(obj); ASN1_INTEGER_free(a); return NULL; } /* * Handle missing NIDs. */ static int create_missing_nids(void) { int i; for (i = 0; i < (int) (sizeof(missing_nids) / sizeof(*missing_nids)); i++) if ((*missing_nids[i].nid = OBJ_txt2nid(missing_nids[i].oid)) == NID_undef && (*missing_nids[i].nid = OBJ_create(missing_nids[i].oid, missing_nids[i].sn, missing_nids[i].ln)) == NID_undef) return 0; return 1; } /* * Convert an OpenSSL OID to a Python string. */ static PyObject * ASN1_OBJECT_to_PyString(const ASN1_OBJECT *oid) { PyObject *result = NULL; char buf[512]; ENTERING(ASN1_OBJECT_to_PyString); if (OBJ_obj2txt(buf, sizeof(buf), oid, 1) <= 0) lose_openssl_error("Couldn't translate OID"); result = PyString_FromString(buf); error: return result; } /* * RFC 5480 2.1.1 requires EC keys to use namedCurve rather than * specificCurve. For some reason OpenSSL defaults to specificCurve, * and there's no function in the high-level API to change this. So * this is icky, but I don't see how to do better without API support. * * This can be called on any EVP_PKEY, but only whacks EC keys, so the * rest of the code can just call this and not worry about what kind * of key it has. */ static void whack_ec_key_to_namedCurve(EVP_PKEY *pkey) { EC_KEY *ec_key; ENTERING(whack_ec_key_to_namedCurve); if (pkey != NULL && EVP_PKEY_id(pkey) == EVP_PKEY_EC && (ec_key = EVP_PKEY_get0(pkey)) != NULL) EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE); } /* * Extension functions. Calling sequence here is a little weird, * because it turns out that the simplest way to avoid massive * duplication of code between classes is to work directly with * X509_EXTENSIONS objects. */ #define EXTENSION_GET_KEY_USAGE__DOC__ \ "Return a FrozenSet of strings representing the KeyUsage settings\n" \ "for this object, or None if the object has no KeyUsage\n" \ "extension. The bits have the same names as in RFC 5280.\n" static PyObject * extension_get_key_usage(X509_EXTENSIONS **exts) { ASN1_BIT_STRING *ext = NULL; PyObject *result = NULL; PyObject *token = NULL; int bit = -1; ENTERING(extension_get_key_usage); if (!exts) goto error; if ((ext = X509V3_get_d2i(*exts, NID_key_usage, NULL, NULL)) == NULL) Py_RETURN_NONE; if ((result = PyFrozenSet_New(NULL)) == NULL) goto error; for (bit = 0; key_usage_bit_names[bit] != NULL; bit++) { if (ASN1_BIT_STRING_get_bit(ext, bit) && ((token = PyString_FromString(key_usage_bit_names[bit])) == NULL || PySet_Add(result, token) < 0)) goto error; Py_XDECREF(token); token = NULL; } ASN1_BIT_STRING_free(ext); return result; error: ASN1_BIT_STRING_free(ext); Py_XDECREF(token); Py_XDECREF(result); return NULL; } #define EXTENSION_SET_KEY_USAGE__DOC__ \ "Argument \"iterable\" should be an iterable object which returns zero or more\n" \ "strings naming bits to be enabled. The bits have the same names as in RFC 5280.\n" \ "\n" \ "Optional argument \"critical\" is a boolean indicating whether the extension\n" \ "should be marked as critical or not. RFC 5280 4.2.1.3 says this extension SHOULD\n" \ "be marked as critical when used, so the default is True.\n" static PyObject * extension_set_key_usage(X509_EXTENSIONS **exts, PyObject *args) { ASN1_BIT_STRING *ext = NULL; PyObject *iterable = NULL; PyObject *critical = Py_True; PyObject *iterator = NULL; PyObject *item = NULL; const char *token; int bit = -1; int ok = 0; ENTERING(extension_set_key_usage); if (!exts) goto error; if ((ext = ASN1_BIT_STRING_new()) == NULL) lose_no_memory(); if (!PyArg_ParseTuple(args, "O|O", &iterable, &critical) || (iterator = PyObject_GetIter(iterable)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if ((token = PyString_AsString(item)) == NULL) goto error; for (bit = 0; key_usage_bit_names[bit] != NULL; bit++) if (!strcmp(token, key_usage_bit_names[bit])) break; if (key_usage_bit_names[bit] == NULL) lose("Unrecognized KeyUsage token"); if (!ASN1_BIT_STRING_set_bit(ext, bit, 1)) lose_no_memory(); Py_XDECREF(item); item = NULL; } if (!X509V3_add1_i2d(exts, NID_key_usage, ext, PyObject_IsTrue(critical), X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add KeyUsage extension to OpenSSL object"); ok = 1; error: /* Fall through */ ASN1_BIT_STRING_free(ext); Py_XDECREF(iterator); Py_XDECREF(item); if (ok) Py_RETURN_NONE; else return NULL; } #define EXTENSION_GET_BASIC_CONSTRAINTS__DOC__ \ "If there is no BasicConstraints extension, this method returns None.\n" \ "\n" \ "Otherwise, this method returns a two-element tuple. The first element\n" \ "of the tuple is a boolean representing the extension's cA value; the\n" \ "second element of the tuple is either an integer representing the\n" \ "pathLenConstraint value or None if there is no pathLenConstraint.\n" static PyObject * extension_get_basic_constraints(X509_EXTENSIONS **exts) { BASIC_CONSTRAINTS *ext = NULL; PyObject *result = NULL; ENTERING(extension_get_basic_constraints); if (!exts) goto error; if ((ext = X509V3_get_d2i(*exts, NID_basic_constraints, NULL, NULL)) == NULL) Py_RETURN_NONE; if (ext->pathlen == NULL) result = Py_BuildValue("(NO)", PyBool_FromLong(ext->ca), Py_None); else result = Py_BuildValue("(Nl)", PyBool_FromLong(ext->ca), ASN1_INTEGER_get(ext->pathlen)); error: BASIC_CONSTRAINTS_free(ext); return result; } #define EXTENSION_SET_BASIC_CONSTRAINTS__DOC__ \ "First argument \"ca\" is a boolean indicating whether the certificate\n" \ "is a CA certificate or not.\n" \ "\n" \ "Optional second argument \"pathLenConstraint\" is a non-negative integer\n" \ "specifying the pathLenConstraint value for this certificate; this value\n" \ "may only be set for CA certificates." \ "\n" \ "Optional third argument \"critical\" specifies whether the extension\n" \ "should be marked as critical. RFC 5280 4.2.1.9 requires that CA\n" \ "certificates mark this extension as critical, so the default is True.\n" static PyObject * extension_set_basic_constraints(X509_EXTENSIONS **exts, PyObject *args) { BASIC_CONSTRAINTS *ext = NULL; PyObject *is_ca = NULL; PyObject *pathlen_obj = Py_None; PyObject *critical = Py_True; long pathlen = -1; int ok = 0; ENTERING(extension_set_basic_constraints); if (!exts) goto error; if (!PyArg_ParseTuple(args, "O|OO", &is_ca, &pathlen_obj, &critical)) goto error; if (pathlen_obj != Py_None && (pathlen = PyInt_AsLong(pathlen_obj)) < 0) lose_type_error("Bad pathLenConstraint value"); if ((ext = BASIC_CONSTRAINTS_new()) == NULL) lose_no_memory(); ext->ca = PyObject_IsTrue(is_ca) ? 0xFF : 0; if (pathlen_obj != Py_None && ((ext->pathlen == NULL && (ext->pathlen = ASN1_INTEGER_new()) == NULL) || !ASN1_INTEGER_set(ext->pathlen, pathlen))) lose_no_memory(); if (!X509V3_add1_i2d(exts, NID_basic_constraints, ext, PyObject_IsTrue(critical), X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add BasicConstraints extension to OpenSSL object"); ok = 1; error: BASIC_CONSTRAINTS_free(ext); if (ok) Py_RETURN_NONE; else return NULL; } #define EXTENSION_GET_SIA__DOC__ \ "If there is no SIA extension, this method returns None.\n" \ "\n" \ "Otherwise, it returns a tuple containing four values:\n" \ "caRepository URIs, rpkiManifest URIs, signedObject, and rpkiNotify URIs.\n" \ "Each of these values is a tuple of strings, representing an ordered\n" \ "sequence of URIs. Any or all of these sequences may be empty.\n" \ "\n" \ "Any other accessMethods are ignored, as are any non-URI accessLocations.\n" static PyObject * extension_get_sia(X509_EXTENSIONS **exts) { AUTHORITY_INFO_ACCESS *ext = NULL; PyObject *result = NULL; PyObject *result_caRepository = NULL; PyObject *result_rpkiManifest = NULL; PyObject *result_signedObject = NULL; PyObject *result_rpkiNotify = NULL; int n_caRepository = 0; int n_rpkiManifest = 0; int n_signedObject = 0; int n_rpkiNotify = 0; const char *uri; PyObject *obj; int i, nid; ENTERING(pkcs10_object_get_sia); if (!exts) goto error; if ((ext = X509V3_get_d2i(*exts, NID_sinfo_access, NULL, NULL)) == NULL) Py_RETURN_NONE; /* * Easiest to do this in two passes, first pass just counts URIs. */ for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ext); i++) { ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(ext, i); if (a->location->type != GEN_URI) continue; nid = OBJ_obj2nid(a->method); if (nid == NID_caRepository) n_caRepository++; else if (nid == NID_rpkiManifest) n_rpkiManifest++; else if (nid == NID_signedObject) n_signedObject++; else if (nid == NID_rpkiNotify) n_rpkiNotify++; } if (((result_caRepository = PyTuple_New(n_caRepository)) == NULL) || ((result_rpkiManifest = PyTuple_New(n_rpkiManifest)) == NULL) || ((result_signedObject = PyTuple_New(n_signedObject)) == NULL) || ((result_rpkiNotify = PyTuple_New(n_rpkiNotify)) == NULL)) goto error; n_caRepository = n_rpkiManifest = n_signedObject = n_rpkiNotify = 0; for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ext); i++) { ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(ext, i); if (a->location->type != GEN_URI) continue; nid = OBJ_obj2nid(a->method); uri = (char *) ASN1_STRING_data(a->location->d.uniformResourceIdentifier); if (nid == NID_caRepository) { if ((obj = PyString_FromString(uri)) == NULL) goto error; PyTuple_SET_ITEM(result_caRepository, n_caRepository++, obj); continue; } if (nid == NID_rpkiManifest) { if ((obj = PyString_FromString(uri)) == NULL) goto error; PyTuple_SET_ITEM(result_rpkiManifest, n_rpkiManifest++, obj); continue; } if (nid == NID_signedObject) { if ((obj = PyString_FromString(uri)) == NULL) goto error; PyTuple_SET_ITEM(result_signedObject, n_signedObject++, obj); continue; } if (nid == NID_rpkiNotify) { if ((obj = PyString_FromString(uri)) == NULL) goto error; PyTuple_SET_ITEM(result_rpkiNotify, n_rpkiNotify++, obj); continue; } } result = Py_BuildValue("(OOOO)", result_caRepository, result_rpkiManifest, result_signedObject, result_rpkiNotify); error: AUTHORITY_INFO_ACCESS_free(ext); Py_XDECREF(result_caRepository); Py_XDECREF(result_rpkiManifest); Py_XDECREF(result_signedObject); Py_XDECREF(result_rpkiNotify); return result; } #define EXTENSION_SET_SIA__DOC__ \ "This method takes four arguments: \"caRepository\"\n," \ "\"rpkiManifest\", \"signedObject\", and \"rpkiNotify\".\n" \ "Each of these should be an iterable which returns URIs.\n" \ "\n" \ "None is acceptable as an alternate way of specifying an empty\n" \ "collection of URIs for a particular argument.\n" static PyObject * extension_set_sia(X509_EXTENSIONS **exts, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"caRepository", "rpkiManifest", "signedObject", "rpkiNotify", NULL}; AUTHORITY_INFO_ACCESS *ext = NULL; PyObject *caRepository = Py_None; PyObject *rpkiManifest = Py_None; PyObject *signedObject = Py_None; PyObject *rpkiNotify = Py_None; PyObject *iterator = NULL; ASN1_OBJECT *oid = NULL; PyObject **pobj = NULL; PyObject *item = NULL; ACCESS_DESCRIPTION *a = NULL; int i, nid = NID_undef, ok = 0; Py_ssize_t urilen; char *uri; ENTERING(extension_set_sia); if (!exts) goto error; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &caRepository, &rpkiManifest, &signedObject, &rpkiNotify)) goto error; if ((ext = AUTHORITY_INFO_ACCESS_new()) == NULL) lose_no_memory(); /* * This is going to want refactoring, because it's ugly, because we * want to reuse code for AIA, and because it'd be nice to support a * single URI as an abbreviation for a collection containing one URI. */ for (i = 0; i < 4; i++) { switch (i) { case 0: pobj = &caRepository; nid = NID_caRepository; break; case 1: pobj = &rpkiManifest; nid = NID_rpkiManifest; break; case 2: pobj = &signedObject; nid = NID_signedObject; break; case 3: pobj = &rpkiNotify; nid = NID_rpkiNotify; break; } if (*pobj == Py_None) continue; if ((oid = OBJ_nid2obj(nid)) == NULL) lose_openssl_error("Couldn't find SIA accessMethod OID"); if ((iterator = PyObject_GetIter(*pobj)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if (PyString_AsStringAndSize(item, &uri, &urilen) < 0) goto error; if ((a = ACCESS_DESCRIPTION_new()) == NULL || (a->method = OBJ_dup(oid)) == NULL || (a->location->d.uniformResourceIdentifier = ASN1_IA5STRING_new()) == NULL || !ASN1_OCTET_STRING_set(a->location->d.uniformResourceIdentifier, (unsigned char *) uri, urilen)) lose_no_memory(); a->location->type = GEN_URI; if (!sk_ACCESS_DESCRIPTION_push(ext, a)) lose_no_memory(); a = NULL; Py_XDECREF(item); item = NULL; } Py_XDECREF(iterator); iterator = NULL; } if (!X509V3_add1_i2d(exts, NID_sinfo_access, ext, 0, X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add SIA extension to OpenSSL object"); ok = 1; error: AUTHORITY_INFO_ACCESS_free(ext); ACCESS_DESCRIPTION_free(a); Py_XDECREF(item); Py_XDECREF(iterator); if (ok) Py_RETURN_NONE; else return NULL; } #define EXTENSION_GET_EKU__DOC__ \ "Return a FrozenSet of object identifiers representing the\n" \ "ExtendedKeyUsage settings for this object, or None if the object\n" \ "has no ExtendedKeyUsage extension.\n" static PyObject * extension_get_eku(X509_EXTENSIONS **exts) { EXTENDED_KEY_USAGE *ext = NULL; PyObject *result = NULL; PyObject *oid = NULL; int i; ENTERING(extension_get_eku); if (!exts) goto error; if ((ext = X509V3_get_d2i(*exts, NID_ext_key_usage, NULL, NULL)) == NULL) Py_RETURN_NONE; if ((result = PyFrozenSet_New(NULL)) == NULL) goto error; for (i = 0; i < sk_ASN1_OBJECT_num(ext); i++) { if ((oid = ASN1_OBJECT_to_PyString(sk_ASN1_OBJECT_value(ext, i))) == NULL || PySet_Add(result, oid) < 0) goto error; Py_XDECREF(oid); oid = NULL; } sk_ASN1_OBJECT_pop_free(ext, ASN1_OBJECT_free); return result; error: sk_ASN1_OBJECT_pop_free(ext, ASN1_OBJECT_free); Py_XDECREF(oid); Py_XDECREF(result); return NULL; } #define EXTENSION_SET_EKU__DOC__ \ "Argument \"iterable\" should be an iterable object which returns one or more\n" \ "object identifiers.\n" \ "\n" \ "Optional argument \"critical\" is a boolean indicating whether the extension\n" \ "should be marked as critical or not. RFC 6487 4.8.5 says this extension\n" \ "MUST NOT be marked as non-critical when used, so the default is False.\n" static PyObject * extension_set_eku(X509_EXTENSIONS **exts, PyObject *args) { EXTENDED_KEY_USAGE *ext = NULL; PyObject *iterable = NULL; PyObject *critical = Py_False; PyObject *iterator = NULL; PyObject *item = NULL; ASN1_OBJECT *obj = NULL; const char *txt; int ok = 0; ENTERING(extension_set_eku); if (!exts) goto error; if ((ext = sk_ASN1_OBJECT_new_null()) == NULL) lose_no_memory(); if (!PyArg_ParseTuple(args, "O|O", &iterable, &critical) || (iterator = PyObject_GetIter(iterable)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if ((txt = PyString_AsString(item)) == NULL) goto error; if ((obj = OBJ_txt2obj(txt, 1)) == NULL) lose("Couldn't parse OID"); if (!sk_ASN1_OBJECT_push(ext, obj)) lose_no_memory(); obj = NULL; Py_XDECREF(item); item = NULL; } if (sk_ASN1_OBJECT_num(ext) < 1) lose("Empty ExtendedKeyUsage extension"); if (!X509V3_add1_i2d(exts, NID_ext_key_usage, ext, PyObject_IsTrue(critical), X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add ExtendedKeyUsage extension to OpenSSL object"); ok = 1; error: /* Fall through */ sk_ASN1_OBJECT_pop_free(ext, ASN1_OBJECT_free); Py_XDECREF(item); Py_XDECREF(iterator); if (ok) Py_RETURN_NONE; else return NULL; } #define EXTENSION_GET_SKI__DOC__ \ "Return the Subject Key Identifier (SKI) value for this object,\n" \ "or None if the object has no SKI extension.\n" static PyObject * extension_get_ski(X509_EXTENSIONS **exts) { ASN1_OCTET_STRING *ext = NULL; PyObject *result = NULL; ENTERING(extension_get_ski); if (!exts) goto error; if ((ext = X509V3_get_d2i(*exts, NID_subject_key_identifier, NULL, NULL)) == NULL) Py_RETURN_NONE; result = Py_BuildValue("s#", ASN1_STRING_data(ext), (Py_ssize_t) ASN1_STRING_length(ext)); error: /* Fall through */ ASN1_OCTET_STRING_free(ext); return result; } #define EXTENSION_SET_SKI__DOC__ \ "Set the Subject Key Identifier (SKI) value for this object.\n" static PyObject * extension_set_ski(X509_EXTENSIONS **exts, PyObject *args) { ASN1_OCTET_STRING *ext = NULL; const unsigned char *buf = NULL; Py_ssize_t len; int ok = 0; ENTERING(extension_set_ski); if (!exts) goto error; if (!PyArg_ParseTuple(args, "s#", &buf, &len)) goto error; if ((ext = ASN1_OCTET_STRING_new()) == NULL || !ASN1_OCTET_STRING_set(ext, buf, len)) lose_no_memory(); /* * RFC 5280 says this MUST be non-critical. */ if (!X509V3_add1_i2d(exts, NID_subject_key_identifier, ext, 0, X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add SKI extension to OpenSSL object"); ok = 1; error: ASN1_OCTET_STRING_free(ext); if (ok) Py_RETURN_NONE; else return NULL; } #define EXTENSION_GET_AKI__DOC__ \ "Return the Authority Key Identifier (AKI) keyid value for this object,\n" \ "or None if the object has no AKI extension or has an AKI extension with\n" \ "no keyIdentifier value.\n" static PyObject * extension_get_aki(X509_EXTENSIONS **exts) { AUTHORITY_KEYID *ext = NULL; PyObject *result = NULL; ENTERING(extension_get_aki); if (!exts) goto error; if ((ext = X509V3_get_d2i(*exts, NID_authority_key_identifier, NULL, NULL)) == NULL) Py_RETURN_NONE; result = Py_BuildValue("s#", ASN1_STRING_data(ext->keyid), (Py_ssize_t) ASN1_STRING_length(ext->keyid)); error: /* Fall through */ AUTHORITY_KEYID_free(ext); return result; } #define EXTENSION_SET_AKI__DOC__ \ "Set the Authority Key Identifier (AKI) value for this object.\n" \ "\n" \ "We only support the keyIdentifier method, as that's the only form\n" \ "which is legal for RPKI certificates.\n" static PyObject * extension_set_aki(X509_EXTENSIONS **exts, PyObject *args) { AUTHORITY_KEYID *ext = NULL; const unsigned char *buf = NULL; Py_ssize_t len; int ok = 0; ENTERING(extension_set_aki); assert (exts); if (!PyArg_ParseTuple(args, "s#", &buf, &len)) goto error; if ((ext = AUTHORITY_KEYID_new()) == NULL || (ext->keyid == NULL && (ext->keyid = ASN1_OCTET_STRING_new()) == NULL) || !ASN1_OCTET_STRING_set(ext->keyid, buf, len)) lose_no_memory(); /* * RFC 5280 says this MUST be non-critical. */ if (!X509V3_add1_i2d(exts, NID_authority_key_identifier, ext, 0, X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add AKI extension to OpenSSL object"); ok = 1; error: AUTHORITY_KEYID_free(ext); if (ok) Py_RETURN_NONE; else return NULL; } /* * IPAddress object. */ static PyObject * ipaddress_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"initializer", "version", NULL}; ipaddress_object *self = NULL; PyObject *init = NULL; PyObject *pylong = NULL; int version = 0; const char *s = NULL; int v; ENTERING(ipaddress_object_new); if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &init, &version) || (self = (ipaddress_object *) type->tp_alloc(type, 0)) == NULL) goto error; if (POW_IPAddress_Check(init)) { ipaddress_object *src = (ipaddress_object *) init; memcpy(self->address, src->address, sizeof(self->address)); self->type = src->type; return (PyObject *) self; } if ((s = PyString_AsString(init)) == NULL) PyErr_Clear(); else if (version == 0) version = strchr(s, ':') ? 6 : 4; self->type = NULL; for (v = 0; v < (int) (sizeof(ipaddress_versions)/sizeof(*ipaddress_versions)); v++) if ((unsigned) version == ipaddress_versions[v]->version) self->type = ipaddress_versions[v]; if (self->type == NULL) lose("Unknown IP version number"); if (s != NULL) { if (inet_pton(self->type->af, s, self->address) <= 0) lose("Couldn't parse IP address"); return (PyObject *) self; } if ((pylong = PyNumber_Long(init)) != NULL) { if (_PyLong_AsByteArray((PyLongObject *) pylong, self->address, self->type->length, 0, 0) < 0) goto error; Py_XDECREF(pylong); return (PyObject *) self; } lose_type_error("Couldn't convert initializer to IPAddress"); error: Py_XDECREF(self); Py_XDECREF(pylong); return NULL; } static PyObject * ipaddress_object_str(ipaddress_object *self) { char addrstr[sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:255.255.255.255") + 1]; ENTERING(ipaddress_object_str); if (!inet_ntop(self->type->af, self->address, addrstr, sizeof(addrstr))) lose("Couldn't convert IP address"); return PyString_FromString(addrstr); error: return NULL; } static PyObject * ipaddress_object_repr(ipaddress_object *self) { char addrstr[sizeof("aaaa:bbbb:cccc:dddd:eeee:ffff:255.255.255.255") + 1]; ENTERING(ipaddress_object_repr); if (!inet_ntop(self->type->af, self->address, addrstr, sizeof(addrstr))) lose("Couldn't convert IP address"); return PyString_FromFormat("<%s object %s at %p>", self->ob_type->tp_name, addrstr, self); error: return NULL; } static int ipaddress_object_compare(PyObject *arg1, PyObject *arg2) { PyObject *obj1 = PyNumber_Long(arg1); PyObject *obj2 = PyNumber_Long(arg2); int cmp = -1; ENTERING(ipaddress_object_compare); if (obj1 != NULL && obj2 != NULL) cmp = PyObject_Compare(obj1, obj2); Py_XDECREF(obj1); Py_XDECREF(obj2); return cmp; } static PyObject * ipaddress_object_richcompare(PyObject *arg1, PyObject *arg2, int op) { PyObject *obj1 = PyNumber_Long(arg1); PyObject *obj2 = PyNumber_Long(arg2); PyObject *result = NULL; ENTERING(ipaddress_object_richcompare); if (obj1 != NULL && obj2 != NULL) result = PyObject_RichCompare(obj1, obj2, op); Py_XDECREF(obj1); Py_XDECREF(obj2); return result; } static long ipaddress_object_hash(ipaddress_object *self) { unsigned long h = 0; int i; ENTERING(ipaddress_object_hash); for (i = 0; (unsigned) i < self->type->length; i++) h ^= self->address[i] << ((i & 3) << 3); return (long) h == -1 ? 0 : (long) h; } static char ipaddress_object_from_bytes__doc__[] = "Construct an IPAddress object from a sequence of bytes.\n" "\n" "Argument must be a Python string of exactly 4 or 16 bytes.\n" ; static PyObject * ipaddress_object_from_bytes(PyTypeObject *type, PyObject *args) { ipaddress_object *result = NULL; char *bytes = NULL; Py_ssize_t len; int v; ENTERING(ipaddress_object_from_bytes); if (!PyArg_ParseTuple(args, "s#", &bytes, &len)) goto error; if ((result = (ipaddress_object *) type->tp_alloc(type, 0)) == NULL) goto error; result->type = NULL; for (v = 0; v < (int) (sizeof(ipaddress_versions)/sizeof(*ipaddress_versions)); v++) if (len == ipaddress_versions[v]->length) result->type = ipaddress_versions[v]; if (result->type == NULL) lose("Unknown IP version number"); memcpy(result->address, bytes, len); return (PyObject *) result; error: Py_XDECREF(result); return NULL; } static char ipaddress_object_to_bytes__doc__[] = "Return the binary value of this IPAddress as a Python string\n" "of exactly 4 or 16 bytes.\n" ; static PyObject * ipaddress_object_to_bytes(ipaddress_object *self) { ENTERING(ipaddress_object_from_bytes); return PyString_FromStringAndSize((char *) self->address, self->type->length); } static PyObject * ipaddress_object_get_bits(ipaddress_object *self, GCC_UNUSED void *closure) { ENTERING(ipaddress_object_get_bits); return PyInt_FromLong(self->type->length * 8); } static PyObject * ipaddress_object_get_version(ipaddress_object *self, GCC_UNUSED void *closure) { ENTERING(ipaddress_object_get_version); return PyInt_FromLong(self->type->version); } static PyObject * ipaddress_object_number_binary_helper(binaryfunc function, PyObject *arg1, PyObject *arg2) { ipaddress_object *addr = NULL; ipaddress_object *addr1 = NULL; ipaddress_object *addr2 = NULL; ipaddress_object *result = NULL; PyObject *obj1 = NULL; PyObject *obj2 = NULL; PyObject *obj3 = NULL; PyObject *obj4 = NULL; if (POW_IPAddress_Check(arg1)) addr1 = (ipaddress_object *) arg1; if (POW_IPAddress_Check(arg2)) addr2 = (ipaddress_object *) arg2; if ((addr1 == NULL && addr2 == NULL) || (addr1 != NULL && addr2 != NULL && addr1->type != addr2->type) || (obj1 = PyNumber_Long(arg1)) == NULL || (obj2 = PyNumber_Long(arg2)) == NULL) { result = (ipaddress_object *) Py_NotImplemented; Py_INCREF(result); goto error; } if ((obj3 = function(obj1, obj2)) == NULL) goto error; if ((obj4 = PyNumber_Long(obj3)) == NULL) lose("Couldn't convert result"); addr = addr1 != NULL ? addr1 : addr2; if ((result = (ipaddress_object *) addr->ob_type->tp_alloc(addr->ob_type, 0)) == NULL) goto error; result->type = addr->type; if (_PyLong_AsByteArray((PyLongObject *) obj4, result->address, result->type->length, 0, 0) < 0) { Py_XDECREF(result); result = NULL; } error: /* Fall through */ Py_XDECREF(obj1); Py_XDECREF(obj2); Py_XDECREF(obj3); Py_XDECREF(obj4); return (PyObject *) result; } static PyObject * ipaddress_object_number_long(PyObject *arg) { ipaddress_object *addr = (ipaddress_object *) arg; ENTERING(ipaddress_object_number_long); if (!POW_IPAddress_Check(arg)) return Py_INCREF(Py_NotImplemented), Py_NotImplemented; return _PyLong_FromByteArray(addr->address, addr->type->length, 0, 0); } static PyObject * ipaddress_object_number_int(PyObject *arg) { ENTERING(ipaddress_object_number_int); return ipaddress_object_number_long(arg); } static PyObject * ipaddress_object_number_add(PyObject *arg1, PyObject *arg2) { ENTERING(ipaddress_object_number_add); return ipaddress_object_number_binary_helper(PyNumber_Add, arg1, arg2); } static PyObject * ipaddress_object_number_subtract(PyObject *arg1, PyObject *arg2) { ENTERING(ipaddress_object_number_subtract); return ipaddress_object_number_binary_helper(PyNumber_Subtract, arg1, arg2); } static PyObject * ipaddress_object_number_lshift(PyObject *arg1, PyObject *arg2) { ENTERING(ipaddress_object_number_lshift); return ipaddress_object_number_binary_helper(PyNumber_Lshift, arg1, arg2); } static PyObject * ipaddress_object_number_rshift(PyObject *arg1, PyObject *arg2) { ENTERING(ipaddress_object_number_rshift); return ipaddress_object_number_binary_helper(PyNumber_Rshift, arg1, arg2); } static PyObject * ipaddress_object_number_and(PyObject *arg1, PyObject *arg2) { ENTERING(ipaddress_object_number_and); return ipaddress_object_number_binary_helper(PyNumber_And, arg1, arg2); } static PyObject * ipaddress_object_number_xor(PyObject *arg1, PyObject *arg2) { ENTERING(ipaddress_object_number_xor); return ipaddress_object_number_binary_helper(PyNumber_Xor, arg1, arg2); } static PyObject * ipaddress_object_number_or(PyObject *arg1, PyObject *arg2) { ENTERING(ipaddress_object_number_or); return ipaddress_object_number_binary_helper(PyNumber_Or, arg1, arg2); } static int ipaddress_object_number_nonzero(ipaddress_object *self) { int i; ENTERING(ipaddress_object_number_nonzero); for (i = 0; (unsigned) i < self->type->length; i++) if (self->address[i] != 0) return 1; return 0; } static PyObject * ipaddress_object_number_invert(ipaddress_object *self) { ipaddress_object *result = NULL; int i; ENTERING(ipaddress_object_number_invert); if ((result = (ipaddress_object *) self->ob_type->tp_alloc(self->ob_type, 0)) == NULL) goto error; result->type = self->type; for (i = 0; (unsigned) i < self->type->length; i++) result->address[i] = ~self->address[i]; error: /* Fall through */ return (PyObject *) result; } static char ipaddress_object_copy__doc__[] = "Copy an IPAddress object.\n" ; static PyObject * ipaddress_object_copy(ipaddress_object *self, GCC_UNUSED PyObject *args) { ipaddress_object *result = NULL; ENTERING(ipaddress_object_copy); if ((result = (ipaddress_object *) self->ob_type->tp_alloc(self->ob_type, 0)) == NULL) goto error; memcpy(result->address, self->address, sizeof(result->address)); result->type = self->type; error: return (PyObject *) result; } static struct PyMethodDef ipaddress_object_methods[] = { Define_Method(__copy__, ipaddress_object_copy, METH_VARARGS), Define_Method(__deepcopy__, ipaddress_object_copy, METH_VARARGS), Define_Method(toBytes, ipaddress_object_to_bytes, METH_NOARGS), Define_Class_Method(fromBytes, ipaddress_object_from_bytes, METH_VARARGS), {NULL} }; static PyGetSetDef ipaddress_object_getsetters[] = { {"bits", (getter) ipaddress_object_get_bits}, {"version", (getter) ipaddress_object_get_version}, {NULL} }; static PyNumberMethods ipaddress_NumberMethods = { ipaddress_object_number_add, /* nb_add */ ipaddress_object_number_subtract, /* nb_subtract */ 0, /* nb_multiply */ 0, /* nb_divide */ 0, /* nb_remainder */ 0, /* nb_divmod */ 0, /* nb_power */ 0, /* nb_negative */ 0, /* nb_positive */ 0, /* nb_absolute */ (inquiry) ipaddress_object_number_nonzero, /* nb_nonzero */ (unaryfunc) ipaddress_object_number_invert, /* nb_invert */ ipaddress_object_number_lshift, /* nb_lshift */ ipaddress_object_number_rshift, /* nb_rshift */ ipaddress_object_number_and, /* nb_and */ ipaddress_object_number_xor, /* nb_xor */ ipaddress_object_number_or, /* nb_or */ 0, /* nb_coerce */ ipaddress_object_number_int, /* nb_int */ ipaddress_object_number_long, /* nb_long */ 0, /* nb_float */ 0, /* nb_oct */ 0, /* nb_hex */ 0, /* nb_inplace_add */ 0, /* nb_inplace_subtract */ 0, /* nb_inplace_multiply */ 0, /* nb_inplace_divide */ 0, /* nb_inplace_remainder */ 0, /* nb_inplace_power */ 0, /* nb_inplace_lshift */ 0, /* nb_inplace_rshift */ 0, /* nb_inplace_and */ 0, /* nb_inplace_xor */ 0, /* nb_inplace_or */ 0, /* nb_floor_divide */ 0, /* nb_true_divide */ 0, /* nb_inplace_floor_divide */ 0, /* nb_inplace_true_divide */ 0, /* nb_index */ }; static PyTypeObject POW_IPAddress_Type = { PyObject_HEAD_INIT(NULL) 0, /* ob_size */ "rpki.POW.IPAddress", /* tp_name */ sizeof(ipaddress_object), /* tp_basicsize */ 0, /* tp_itemsize */ 0, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ ipaddress_object_compare, /* tp_compare */ (reprfunc) ipaddress_object_repr, /* tp_repr */ &ipaddress_NumberMethods, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ (hashfunc) ipaddress_object_hash, /* tp_hash */ 0, /* tp_call */ (reprfunc) ipaddress_object_str, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ ipaddress_object_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ ipaddress_object_methods, /* tp_methods */ 0, /* tp_members */ ipaddress_object_getsetters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ ipaddress_object_new, /* tp_new */ }; /* * X509 object. */ static x509_object * x509_object_new_helper(PyTypeObject *type, X509 *x) { x509_object *self; if (type == NULL) type = &POW_X509_Type; if ((self = (x509_object *) type->tp_alloc(type, 0)) == NULL) return NULL; self->x509 = x; return self; } static PyObject * x509_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { x509_object *self = NULL; X509 *x = NULL; ENTERING(x509_object_new); if ((x = X509_new()) == NULL) lose_no_memory(); if ((self = x509_object_new_helper(type, x)) == NULL) goto error; return (PyObject *) self; error: X509_free(x); return NULL; } static void x509_object_dealloc(x509_object *self) { ENTERING(x509_object_dealloc); X509_free(self->x509); self->ob_type->tp_free((PyObject*) self); } static PyObject * x509_object_pem_read_helper(PyTypeObject *type, BIO *bio) { x509_object *self = NULL; ENTERING(x509_object_pem_read_helper); if ((self = (x509_object *) x509_object_new(type, NULL, NULL)) == NULL) goto error; if (!PEM_read_bio_X509(bio, &self->x509, NULL, NULL)) lose_openssl_error("Couldn't load PEM encoded certificate"); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static PyObject * x509_object_der_read_helper(PyTypeObject *type, BIO *bio) { x509_object *self; ENTERING(x509_object_der_read_helper); if ((self = (x509_object *) x509_object_new(type, NULL, NULL)) == NULL) goto error; if (!d2i_X509_bio(bio, &self->x509)) lose_openssl_error("Couldn't load DER encoded certificate"); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static char x509_object_pem_read__doc__[] = "Read a PEM-encoded X.509 object from a string.\n" ; static PyObject * x509_object_pem_read(PyTypeObject *type, PyObject *args) { ENTERING(x509_object_pem_read); return read_from_string_helper(x509_object_pem_read_helper, type, args); } static char x509_object_pem_read_file__doc__[] = "Read a PEM-encoded X.509 object from a file.\n" ; static PyObject * x509_object_pem_read_file(PyTypeObject *type, PyObject *args) { ENTERING(x509_object_pem_read_file); return read_from_file_helper(x509_object_pem_read_helper, type, args); } static char x509_object_der_read__doc__[] = "Read a DER-encoded X.509 object from a string.\n" ; static PyObject * x509_object_der_read(PyTypeObject *type, PyObject *args) { ENTERING(x509_object_der_read); return read_from_string_helper(x509_object_der_read_helper, type, args); } static char x509_object_der_read_file__doc__[] = "Read a DER-encoded X.509 object from a file.\n" ; static PyObject * x509_object_der_read_file(PyTypeObject *type, PyObject *args) { ENTERING(x509_object_der_read_file); return read_from_file_helper(x509_object_der_read_helper, type, args); } static char x509_object_pem_write__doc__[] = "Return the PEM encoding of this certificate, as a string.\n" ; static PyObject * x509_object_pem_write(x509_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(x509_object_pem_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!PEM_write_bio_X509(bio, self->x509)) lose_openssl_error("Unable to write certificate"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char x509_object_der_write__doc__[] = "Return the DER encoding of this certificate, as a string.\n" ; static PyObject * x509_object_der_write(x509_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(x509_object_der_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!i2d_X509_bio(bio, self->x509)) lose_openssl_error("Unable to write certificate"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static X509_EXTENSIONS ** x509_object_extension_helper(x509_object *self) { if (self && self->x509 && self->x509->cert_info) return &self->x509->cert_info->extensions; PyErr_SetString(PyExc_ValueError, "Can't find X509_EXTENSIONS in X509 object"); return NULL; } static char x509_object_get_public_key__doc__[] = "Return the public key from this certificate object,\n" "as an Asymmetric object.\n" ; static PyObject * x509_object_get_public_key(x509_object *self) { PyTypeObject *type = &POW_Asymmetric_Type; asymmetric_object *asym = NULL; ENTERING(x509_object_get_public_key); if ((asym = (asymmetric_object *) type->tp_alloc(type, 0)) == NULL) goto error; if ((asym->pkey = X509_get_pubkey(self->x509)) == NULL) lose_openssl_error("Couldn't extract public key from certificate"); whack_ec_key_to_namedCurve(asym->pkey); return (PyObject *) asym; error: Py_XDECREF(asym); return NULL; } static char x509_object_set_public_key__doc__[] = "Set the public key of this certificate object.\n" "\n" "The \"key\" parameter should be an instance of the Asymmetric class,\n" "containing a public key.\n" ; static PyObject * x509_object_set_public_key(x509_object *self, PyObject *args) { asymmetric_object *asym; ENTERING(x509_object_set_public_key); if (!PyArg_ParseTuple(args, "O!", &POW_Asymmetric_Type, &asym)) goto error; if (!X509_set_pubkey(self->x509, asym->pkey)) lose_openssl_error("Couldn't set certificate's public key"); Py_RETURN_NONE; error: return NULL; } static char x509_object_sign__doc__[] = "Sign a certificate with a private key.\n" "\n" "The \"key\" parameter should be an instance of the Asymmetric class,\n" "containing a private key.\n" "\n" "The optional \"digest\" parameter indicates which digest to compute and\n" "sign, and should be one of the following:\n" "\n" "* MD5_DIGEST\n" "* SHA_DIGEST\n" "* SHA1_DIGEST\n" "* SHA256_DIGEST\n" "* SHA384_DIGEST\n" "* SHA512_DIGEST\n" "\n" "The default digest algorithm is SHA-256.\n" ; static PyObject * x509_object_sign(x509_object *self, PyObject *args) { asymmetric_object *asym; int digest_type = SHA256_DIGEST; const EVP_MD *digest_method = NULL; ENTERING(x509_object_sign); if (!PyArg_ParseTuple(args, "O!|i", &POW_Asymmetric_Type, &asym, &digest_type)) goto error; if ((digest_method = evp_digest_factory(digest_type)) == NULL) lose("Unsupported digest algorithm"); if (!X509_sign(self->x509, asym->pkey, digest_method)) lose_openssl_error("Couldn't sign certificate"); Py_RETURN_NONE; error: return NULL; } static char x509_object_get_version__doc__[] = "Return version number of this certificate.\n" ; static PyObject * x509_object_get_version(x509_object *self) { ENTERING(x509_object_get_version); return Py_BuildValue("l", X509_get_version(self->x509)); } static char x509_object_set_version__doc__[] = "Set version number of this certificate.\n" "\n" "The \"version\" parameter should be an integer.\n" ; static PyObject * x509_object_set_version(x509_object *self, PyObject *args) { long version = 0; ENTERING(x509_object_set_version); if (!PyArg_ParseTuple(args, "l", &version)) goto error; if (!X509_set_version(self->x509, version)) lose("Couldn't set certificate version"); Py_RETURN_NONE; error: return NULL; } static char x509_object_get_serial__doc__[] = "Return the serial number of this certificate.\n" ; static PyObject * x509_object_get_serial(x509_object *self) { ENTERING(x509_object_get_serial); return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(X509_get_serialNumber(self->x509))); } static char x509_object_set_serial__doc__[] = "Set the serial number of this certificate.\n" "\n" "The \"serial\" parameter should ba an integer.\n" ; static PyObject * x509_object_set_serial(x509_object *self, PyObject *args) { ASN1_INTEGER *a_serial = NULL; PyObject *p_serial = NULL; int ok = 0; ENTERING(x509_object_set_serial); if (!PyArg_ParseTuple(args, "O", &p_serial) || (a_serial = PyLong_to_ASN1_INTEGER(p_serial)) == NULL) goto error; if (!X509_set_serialNumber(self->x509, a_serial)) lose_no_memory(); ok = 1; error: ASN1_INTEGER_free(a_serial); if (ok) Py_RETURN_NONE; else return NULL; } static char x509_object_get_issuer__doc__[] = "Return this certificate's issuer name, represented as a tuple.\n" "\n" "Each element of this tuple is another tuple representing one\n" "\"Relative Distinguished Name\" (RDN), each element of which in turn\n" "is yet another tuple representing one AttributeTypeAndValue pair.\n" "\n" "In practice, RDNs containing multiple attributes are rare, thus the RDN\n" "tuples will usually be exactly one element long, but using the\n" "tuple-of-tuples-of-tuples format lets us represent the general case.\n" "\n" "The AttributeTypeANdValue pairs are two-element tuples, the first\n" "element of which is a string representing an Object Identifier (OID),\n" "the second of which contains the attribute value.\n" "\n" "This method takes an optional \"format\" parameter which controls\n" "the format in which OIDs are returned. Allowed values are:\n" "\n" " * SHORTNAME_FORMAT (the OpenSSL \"short name\" for this OID)\n" " * LONGNAME_FORMAT (the OpenSSL \"long name\" for this OID)\n" " * OIDNAME_FORMAT (the OID in dotted decimal numeric format)\n" "\n" "The default is OIDNAME_FORMAT.\n" "\n" "See RFC 5280 section 4.1.2.4 for details of the ASN.1 structure.\n" ; static PyObject * x509_object_get_issuer(x509_object *self, PyObject *args) { PyObject *result = NULL; int format = OIDNAME_FORMAT; ENTERING(x509_object_get_issuer); if (!PyArg_ParseTuple(args, "|i", &format)) goto error; result = x509_object_helper_get_name(X509_get_issuer_name(self->x509), format); error: /* Fall through */ return result; } static char x509_object_get_subject__doc__[] = "Return this certificate's subject name, as a tuple.\n" "\n" "See the documentation for the \"getIssuer\" method for details on the\n" "structure of the return value and use of the optional \"format\"\n" "parameter.\n" ; static PyObject * x509_object_get_subject(x509_object *self, PyObject *args) { PyObject *result = NULL; int format = OIDNAME_FORMAT; ENTERING(x509_object_get_subject); if (!PyArg_ParseTuple(args, "|i", &format)) goto error; result = x509_object_helper_get_name(X509_get_subject_name(self->x509), format); error: /* Fall through */ return result; } static char x509_object_set_subject__doc__[] = "Set this certificate's subject name.\n" "\n" "The \"name\" parameter should be in the same format as the return\n" "value from the \"getIssuer\" method.\n" ; static PyObject * x509_object_set_subject(x509_object *self, PyObject *args) { PyObject *name_sequence = NULL; X509_NAME *name = NULL; ENTERING(x509_object_set_subject); if (!PyArg_ParseTuple(args, "O", &name_sequence)) goto error; if (!PySequence_Check(name_sequence)) lose_type_error("Inapropriate type"); if ((name = x509_object_helper_set_name(name_sequence)) == NULL) goto error; if (!X509_set_subject_name(self->x509, name)) lose("Unable to set subject name"); X509_NAME_free(name); Py_RETURN_NONE; error: X509_NAME_free(name); return NULL; } static char x509_object_set_issuer__doc__[] = "Set this certificate's issuer name.\n" "\n" "The \"name\" parameter should be in the same format as the return\n" "value from the \"getIssuer\" method.\n" ; static PyObject * x509_object_set_issuer(x509_object *self, PyObject *args) { PyObject *name_sequence = NULL; X509_NAME *name = NULL; ENTERING(x509_object_set_issuer); if (!PyArg_ParseTuple(args, "O", &name_sequence)) goto error; if (!PySequence_Check(name_sequence)) lose_type_error("Inapropriate type"); if ((name = x509_object_helper_set_name(name_sequence)) == NULL) goto error; if (!X509_set_issuer_name(self->x509, name)) lose("Unable to set issuer name"); X509_NAME_free(name); Py_RETURN_NONE; error: X509_NAME_free(name); return NULL; } static char x509_object_get_issuer_hash__doc__[] = "Return the OpenSSL \"name hash\" for this certificate's issuer name.\n" ; static PyObject * x509_object_get_issuer_hash(x509_object *self) { ENTERING(x509_object_get_issuer_hash); return Py_BuildValue("k", X509_NAME_hash(X509_get_issuer_name(self->x509))); } static char x509_object_get_subject_hash__doc__[] = "Return the OpenSSL \"name hash\" for this certificate's subject name.\n" ; static PyObject * x509_object_get_subject_hash(x509_object *self) { ENTERING(x509_object_get_subject_hash); return Py_BuildValue("k", X509_NAME_hash(X509_get_subject_name(self->x509))); } static char x509_object_get_not_before__doc__[] = "Return this certificate's \"notBefore\" value as a datetime.\n" ; static PyObject * x509_object_get_not_before (x509_object *self) { ENTERING(x509_object_get_not_before); return ASN1_TIME_to_Python(X509_get_notBefore(self->x509)); } static char x509_object_get_not_after__doc__[] = "Return this certificate's \"notAfter\" value as a datetime.\n" ; static PyObject * x509_object_get_not_after (x509_object *self) { ENTERING(x509_object_get_not_after); return ASN1_TIME_to_Python(X509_get_notAfter(self->x509)); } static char x509_object_set_not_after__doc__[] = "Set this certificate's \"notAfter\" value.\n" "\n" "The \"time\" parameter should be a datetime object.\n" ; static PyObject * x509_object_set_not_after (x509_object *self, PyObject *args) { PyObject *o = NULL; ASN1_TIME *t = NULL; ENTERING(x509_object_set_not_after); if (!PyArg_ParseTuple(args, "O", &o)) goto error; if ((t = Python_to_ASN1_TIME(o, 1)) == NULL) lose("Couldn't convert notAfter string"); if (!X509_set_notAfter(self->x509, t)) lose("Couldn't set notAfter"); ASN1_TIME_free(t); Py_RETURN_NONE; error: ASN1_TIME_free(t); return NULL; } static char x509_object_set_not_before__doc__[] = "Set this certificate's \"notBefore\" value.\n" "\n" "The \"time\" parameter should be a datetime object.\n" ; static PyObject * x509_object_set_not_before (x509_object *self, PyObject *args) { PyObject *o = NULL; ASN1_TIME *t = NULL; ENTERING(x509_object_set_not_before); if (!PyArg_ParseTuple(args, "O", &o)) goto error; if ((t = Python_to_ASN1_TIME(o, 1)) == NULL) lose("Couldn't convert notBefore string"); if (!X509_set_notBefore(self->x509, t)) lose("Couldn't set notBefore"); ASN1_TIME_free(t); Py_RETURN_NONE; error: ASN1_TIME_free(t); return NULL; } static char x509_object_clear_extensions__doc__[] = "Clear all extensions attached to this certificate.\n" ; static PyObject * x509_object_clear_extensions(x509_object *self) { X509_EXTENSION *ext; ENTERING(x509_object_clear_extensions); while ((ext = X509_delete_ext(self->x509, 0)) != NULL) X509_EXTENSION_free(ext); Py_RETURN_NONE; } static char x509_object_get_ski__doc__[] = EXTENSION_GET_SKI__DOC__ ; static PyObject * x509_object_get_ski(x509_object *self) { return extension_get_ski(x509_object_extension_helper(self)); } static char x509_object_set_ski__doc__[] = EXTENSION_SET_SKI__DOC__ ; static PyObject * x509_object_set_ski(x509_object *self, PyObject *args) { return extension_set_ski(x509_object_extension_helper(self), args); } static char x509_object_get_aki__doc__[] = EXTENSION_GET_AKI__DOC__ ; static PyObject * x509_object_get_aki(x509_object *self) { return extension_get_aki(x509_object_extension_helper(self)); } static char x509_object_set_aki__doc__[] = EXTENSION_SET_AKI__DOC__ ; static PyObject * x509_object_set_aki(x509_object *self, PyObject *args) { return extension_set_aki(x509_object_extension_helper(self), args); } static char x509_object_get_key_usage__doc__[] = EXTENSION_GET_KEY_USAGE__DOC__ ; static PyObject * x509_object_get_key_usage(x509_object *self) { return extension_get_key_usage(x509_object_extension_helper(self)); } static char x509_object_set_key_usage__doc__[] = "Set the KeyUsage extension for this certificate.\n" "\n" EXTENSION_SET_KEY_USAGE__DOC__ ; static PyObject * x509_object_set_key_usage(x509_object *self, PyObject *args) { return extension_set_key_usage(x509_object_extension_helper(self), args); } static char x509_object_get_eku__doc__[] = EXTENSION_GET_EKU__DOC__ ; static PyObject * x509_object_get_eku(x509_object *self) { return extension_get_eku(x509_object_extension_helper(self)); } static char x509_object_set_eku__doc__[] = "Set the ExtendedKeyUsage extension for this certificate.\n" "\n" EXTENSION_SET_EKU__DOC__ ; static PyObject * x509_object_set_eku(x509_object *self, PyObject *args) { return extension_set_eku(x509_object_extension_helper(self), args); } static char x509_object_get_rfc3779__doc__[] = "Return this certificate's RFC 3779 resources.\n" "\n" "Return value is a three-element tuple: the first element is the ASN\n" "resources, the second is the IPv4 resources, the third is the IPv6\n" "resources. Each of these elements in turn can be:\n" "\n" "* None, if this certificate contains no resources of this kind;\n" "\n" "* the string \"inherit\", if this certificate inherits this kind\n" " of resources from its issuer; or\n" "\n" "* a tuple representing a set of ranges of ASNs or IP addresses.\n" "\n" "Each range is a two-element tuple, respectively representing the low\n" "and high ends of the range, inclusive. ASN ranges are represented by\n" "pairs of integers, IP address ranges are represented by pairs of\n" "IPAddress objects.\n" ; static PyObject * x509_object_get_rfc3779(x509_object *self) { PyObject *result = NULL; PyObject *asn_result = NULL; PyObject *ipv4_result = NULL; PyObject *ipv6_result = NULL; PyObject *range = NULL; PyObject *range_b = NULL; PyObject *range_e = NULL; ASIdentifiers *asid = NULL; IPAddrBlocks *addr = NULL; int i, j; ENTERING(x509_object_get_rfc3779); if ((asid = X509_get_ext_d2i(self->x509, NID_sbgp_autonomousSysNum, NULL, NULL)) != NULL && asid->asnum != NULL) { switch (asid->asnum->type) { case ASIdentifierChoice_inherit: if ((asn_result = PyString_FromString("inherit")) == NULL) goto error; break; case ASIdentifierChoice_asIdsOrRanges: if ((asn_result = PyTuple_New(sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges))) == NULL) goto error; for (i = 0; i < sk_ASIdOrRange_num(asid->asnum->u.asIdsOrRanges); i++) { ASIdOrRange *aor = sk_ASIdOrRange_value(asid->asnum->u.asIdsOrRanges, i); ASN1_INTEGER *b = NULL; ASN1_INTEGER *e = NULL; switch (aor->type) { case ASIdOrRange_id: b = e = aor->u.id; break; case ASIdOrRange_range: b = aor->u.range->min; e = aor->u.range->max; break; default: lose_type_error("Unexpected asIdsOrRanges type"); } if (ASN1_STRING_type(b) == V_ASN1_NEG_INTEGER || ASN1_STRING_type(e) == V_ASN1_NEG_INTEGER) lose_type_error("I don't believe in negative ASNs"); if ((range_b = ASN1_INTEGER_to_PyLong(b)) == NULL || (range_e = ASN1_INTEGER_to_PyLong(e)) == NULL || (range = Py_BuildValue("(NN)", range_b, range_e)) == NULL) goto error; PyTuple_SET_ITEM(asn_result, i, range); range = range_b = range_e = NULL; } break; default: lose_type_error("Unexpected ASIdentifierChoice type"); } } if ((addr = X509_get_ext_d2i(self->x509, NID_sbgp_ipAddrBlock, NULL, NULL)) != NULL) { for (i = 0; i < sk_IPAddressFamily_num(addr); i++) { IPAddressFamily *f = sk_IPAddressFamily_value(addr, i); const struct ipaddress_version *ip_type = NULL; const unsigned int afi = v3_addr_get_afi(f); PyObject **result_obj = NULL; int addr_len = 0; switch (afi) { case IANA_AFI_IPV4: result_obj = &ipv4_result; ip_type = &ipaddress_version_4; break; case IANA_AFI_IPV6: result_obj = &ipv6_result; ip_type = &ipaddress_version_6; break; default: lose_type_error("Unknown AFI"); } if (*result_obj != NULL) lose_type_error("Duplicate IPAddressFamily"); if (f->addressFamily->length > 2) lose_type_error("Unsupported SAFI"); switch (f->ipAddressChoice->type) { case IPAddressChoice_inherit: if ((*result_obj = PyString_FromString("inherit")) == NULL) goto error; continue; case IPAddressChoice_addressesOrRanges: break; default: lose_type_error("Unexpected IPAddressChoice type"); } if ((*result_obj = PyTuple_New(sk_IPAddressOrRange_num(f->ipAddressChoice->u.addressesOrRanges))) == NULL) goto error; for (j = 0; j < sk_IPAddressOrRange_num(f->ipAddressChoice->u.addressesOrRanges); j++) { IPAddressOrRange *aor = sk_IPAddressOrRange_value(f->ipAddressChoice->u.addressesOrRanges, j); ipaddress_object *addr_b = NULL; ipaddress_object *addr_e = NULL; if ((range_b = POW_IPAddress_Type.tp_alloc(&POW_IPAddress_Type, 0)) == NULL || (range_e = POW_IPAddress_Type.tp_alloc(&POW_IPAddress_Type, 0)) == NULL) goto error; addr_b = (ipaddress_object *) range_b; addr_e = (ipaddress_object *) range_e; if ((addr_len = v3_addr_get_range(aor, afi, addr_b->address, addr_e->address, sizeof(addr_b->address))) == 0) lose_type_error("Couldn't unpack IP addresses from BIT STRINGs"); addr_b->type = addr_e->type = ip_type; if ((range = Py_BuildValue("(NN)", range_b, range_e)) == NULL) goto error; PyTuple_SET_ITEM(*result_obj, j, range); range = range_b = range_e = NULL; } } } result = Py_BuildValue("(OOO)", (asn_result == NULL ? Py_None : asn_result), (ipv4_result == NULL ? Py_None : ipv4_result), (ipv6_result == NULL ? Py_None : ipv6_result)); error: /* Fall through */ ASIdentifiers_free(asid); sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); Py_XDECREF(range_b); Py_XDECREF(range_e); Py_XDECREF(range); Py_XDECREF(asn_result); Py_XDECREF(ipv4_result); Py_XDECREF(ipv6_result); return result; } static char x509_object_set_rfc3779__doc__[] = "Set this certificate's RFC 3779 resources.\n" "\n" "This method takes three arguments: \"asn\", \"ipv4\", and \"ipv6\".\n" "\n" "Each of these arguments can be:\n" "\n" "* None, to omit this kind of resource;\n" "\n" "* The string \"inherit\", to specify RFC 3779 resource inheritance; or\n" "\n" "* An iterable object which returns range pairs of the appropriate type.\n" "\n" "Range pairs are as returned by the .getRFC3779() method.\n" ; static PyObject * x509_object_set_rfc3779(x509_object *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"asn", "ipv4", "ipv6", NULL}; PyObject *asn_arg = Py_None; PyObject *ipv4_arg = Py_None; PyObject *ipv6_arg = Py_None; PyObject *iterator = NULL; PyObject *item = NULL; PyObject *fast = NULL; ASIdentifiers *asid = NULL; IPAddrBlocks *addr = NULL; ASN1_INTEGER *asid_b = NULL; ASN1_INTEGER *asid_e = NULL; ipaddress_object *addr_b = NULL; ipaddress_object *addr_e = NULL; int empty = 0; ENTERING(x509_object_set_rfc3779); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &asn_arg, &ipv4_arg, &ipv6_arg)) goto error; if (asn_arg != Py_None) { empty = 1; if ((asid = ASIdentifiers_new()) == NULL) lose_no_memory(); if (PyString_Check(asn_arg)) { if (strcmp(PyString_AsString(asn_arg), "inherit")) lose_type_error("ASID must be an iterable that returns range pairs, or the string \"inherit\""); if (!v3_asid_add_inherit(asid, V3_ASID_ASNUM)) lose_no_memory(); empty = 0; } else { if ((iterator = PyObject_GetIter(asn_arg)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if ((fast = PySequence_Fast(item, "ASN range must be a sequence")) == NULL) goto error; if (PySequence_Fast_GET_SIZE(fast) != 2) lose_type_error("ASN range must be two-element sequence"); if ((asid_b = PyLong_to_ASN1_INTEGER(PySequence_Fast_GET_ITEM(fast, 0))) == NULL) goto error; switch (PyObject_RichCompareBool(PySequence_Fast_GET_ITEM(fast, 0), PySequence_Fast_GET_ITEM(fast, 1), Py_EQ)) { case 0: if ((asid_e = PyLong_to_ASN1_INTEGER(PySequence_Fast_GET_ITEM(fast, 1))) == NULL) goto error; break; case 1: break; default: goto error; } if (!v3_asid_add_id_or_range(asid, V3_ASID_ASNUM, asid_b, asid_e)) lose_openssl_error("Couldn't add range to ASID"); asid_b = asid_e = NULL; Py_XDECREF(item); Py_XDECREF(fast); item = fast = NULL; empty = 0; } Py_XDECREF(iterator); iterator = NULL; } if (!empty && (!v3_asid_canonize(asid) || !X509_add1_ext_i2d(self->x509, NID_sbgp_autonomousSysNum, asid, 1, X509V3_ADD_REPLACE))) lose_openssl_error("Couldn't add ASID extension to certificate"); } if (ipv4_arg != Py_None || ipv6_arg != Py_None) { int v; empty = 1; if ((addr = sk_IPAddressFamily_new_null()) == NULL) lose_no_memory(); /* * Cheap trick to let us inline all of this instead of being * forced to use a separate function. Refactor, some day. */ for (v = 0; v < (int) (sizeof(ipaddress_versions)/sizeof(*ipaddress_versions)); v++) { const struct ipaddress_version *ip_type = ipaddress_versions[v]; PyObject **argp; switch (ip_type->version) { case 4: argp = &ipv4_arg; break; case 6: argp = &ipv6_arg; break; default: continue; /* Never happens */ } if (PyString_Check(*argp)) { if (strcmp(PyString_AsString(*argp), "inherit")) lose_type_error("Argument must be an iterable that returns range pairs, or the string \"inherit\""); if (!v3_addr_add_inherit(addr, ip_type->afi, NULL)) lose_no_memory(); empty = 0; } else { if ((iterator = PyObject_GetIter(*argp)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if ((fast = PySequence_Fast(item, "Address range must be a sequence")) == NULL) goto error; if (PySequence_Fast_GET_SIZE(fast) != 2 || !POW_IPAddress_Check(PySequence_Fast_GET_ITEM(fast, 0)) || !POW_IPAddress_Check(PySequence_Fast_GET_ITEM(fast, 1))) lose_type_error("Address range must be two-element sequence of IPAddress objects"); addr_b = (ipaddress_object *) PySequence_Fast_GET_ITEM(fast, 0); addr_e = (ipaddress_object *) PySequence_Fast_GET_ITEM(fast, 1); if (addr_b->type != ip_type || addr_e->type != ip_type || memcmp(addr_b->address, addr_e->address, ip_type->length) > 0) lose("Address range must be two-element sequence of IPAddress objects in ascending order"); if (!v3_addr_add_range(addr, ip_type->afi, NULL, addr_b->address, addr_e->address)) lose_openssl_error("Couldn't add range to IPAddrBlock"); Py_XDECREF(item); Py_XDECREF(fast); item = fast = NULL; addr_b = addr_e = NULL; empty = 0; } Py_XDECREF(iterator); iterator = NULL; } } if (!empty && (!v3_addr_canonize(addr) || !X509_add1_ext_i2d(self->x509, NID_sbgp_ipAddrBlock, addr, 1, X509V3_ADD_REPLACE))) lose_openssl_error("Couldn't add IPAddrBlock extension to certificate"); } Py_RETURN_NONE; error: ASN1_INTEGER_free(asid_b); ASN1_INTEGER_free(asid_e); ASIdentifiers_free(asid); sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free); Py_XDECREF(iterator); Py_XDECREF(item); Py_XDECREF(fast); return NULL; } static char x509_object_get_basic_constraints__doc__[] = "Return BasicConstraints for this certificate.\n" "\n" EXTENSION_GET_BASIC_CONSTRAINTS__DOC__ ; static PyObject * x509_object_get_basic_constraints(x509_object *self) { return extension_get_basic_constraints(x509_object_extension_helper(self)); } static char x509_object_set_basic_constraints__doc__[] = "Set BasicConstraints for this certificate.\n" "\n" EXTENSION_SET_BASIC_CONSTRAINTS__DOC__ ; static PyObject * x509_object_set_basic_constraints(x509_object *self, PyObject *args) { return extension_set_basic_constraints(x509_object_extension_helper(self), args); } static char x509_object_get_sia__doc__[] = "Get SIA values for this certificate.\n" "\n" EXTENSION_GET_SIA__DOC__ ; static PyObject * x509_object_get_sia(x509_object *self) { return extension_get_sia(x509_object_extension_helper(self)); } static char x509_object_set_sia__doc__[] = "Set SIA values for this certificate.\n" "\n" EXTENSION_SET_SIA__DOC__ ; static PyObject * x509_object_set_sia(x509_object *self, PyObject *args, PyObject *kwds) { return extension_set_sia(x509_object_extension_helper(self), args, kwds); } static char x509_object_get_aia__doc__[] = "Get this certificate's AIA values.\n" "\n" "If the certificate has no AIA extension, this method returns None.\n" "\n" "Otherwise, this returns a sequence of caIssuers URIs.\n" "\n" "Any other accessMethods are ignored, as are any non-URI accessLocations.\n" ; static PyObject * x509_object_get_aia(x509_object *self) { AUTHORITY_INFO_ACCESS *ext = NULL; PyObject *result = NULL; const char *uri; PyObject *obj; int i, n = 0; ENTERING(x509_object_get_aia); if ((ext = X509_get_ext_d2i(self->x509, NID_info_access, NULL, NULL)) == NULL) Py_RETURN_NONE; for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ext); i++) { ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(ext, i); if (a->location->type == GEN_URI && OBJ_obj2nid(a->method) == NID_ad_ca_issuers) n++; } if (((result = PyTuple_New(n)) == NULL)) goto error; n = 0; for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ext); i++) { ACCESS_DESCRIPTION *a = sk_ACCESS_DESCRIPTION_value(ext, i); if (a->location->type == GEN_URI && OBJ_obj2nid(a->method) == NID_ad_ca_issuers) { uri = (char *) ASN1_STRING_data(a->location->d.uniformResourceIdentifier); if ((obj = PyString_FromString(uri)) == NULL) goto error; PyTuple_SET_ITEM(result, n++, obj); } } AUTHORITY_INFO_ACCESS_free(ext); return result; error: AUTHORITY_INFO_ACCESS_free(ext); Py_XDECREF(result); return NULL; } static char x509_object_set_aia__doc__[] = "Set AIA URIs for this certificate.\n" "\n" "Argument is a iterable which returns caIssuers URIs.\n" ; static PyObject * x509_object_set_aia(x509_object *self, PyObject *args) { AUTHORITY_INFO_ACCESS *ext = NULL; PyObject *caIssuers = NULL; PyObject *iterator = NULL; ASN1_OBJECT *oid = NULL; PyObject *item = NULL; ACCESS_DESCRIPTION *a = NULL; int ok = 0; Py_ssize_t urilen; char *uri; ENTERING(x509_object_set_aia); if (!PyArg_ParseTuple(args, "O", &caIssuers)) goto error; if ((ext = AUTHORITY_INFO_ACCESS_new()) == NULL) lose_no_memory(); if ((oid = OBJ_nid2obj(NID_ad_ca_issuers)) == NULL) lose_openssl_error("Couldn't find AIA accessMethod OID"); if ((iterator = PyObject_GetIter(caIssuers)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if (PyString_AsStringAndSize(item, &uri, &urilen) < 0) goto error; if ((a = ACCESS_DESCRIPTION_new()) == NULL || (a->method = OBJ_dup(oid)) == NULL || (a->location->d.uniformResourceIdentifier = ASN1_IA5STRING_new()) == NULL || !ASN1_OCTET_STRING_set(a->location->d.uniformResourceIdentifier, (unsigned char *) uri, urilen)) lose_no_memory(); a->location->type = GEN_URI; if (!sk_ACCESS_DESCRIPTION_push(ext, a)) lose_no_memory(); a = NULL; Py_XDECREF(item); item = NULL; } Py_XDECREF(iterator); iterator = NULL; if (!X509_add1_ext_i2d(self->x509, NID_info_access, ext, 0, X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add AIA extension to certificate"); ok = 1; error: AUTHORITY_INFO_ACCESS_free(ext); ACCESS_DESCRIPTION_free(a); Py_XDECREF(item); Py_XDECREF(iterator); if (ok) Py_RETURN_NONE; else return NULL; } static char x509_object_get_crldp__doc__[] = "Get CRL Distribution Point (CRLDP) values for this certificate.\n" "\n" "If the certificate has no CRLDP extension, this method returns None.\n" "\n" "Otherwise, it returns a sequence of URIs representing distributionPoint\n" "fullName values found in the first Distribution Point. Other CRLDP\n" "fields are ignored, as are subsequent Distribution Points and any non-URI\n" "fullName values.\n" ; static PyObject * x509_object_get_crldp(x509_object *self) { CRL_DIST_POINTS *ext = NULL; DIST_POINT *dp = NULL; PyObject *result = NULL; const char *uri; PyObject *obj; int i, n = 0; ENTERING(x509_object_get_crldp); if ((ext = X509_get_ext_d2i(self->x509, NID_crl_distribution_points, NULL, NULL)) == NULL || (dp = sk_DIST_POINT_value(ext, 0)) == NULL || dp->distpoint == NULL || dp->distpoint->type != 0) Py_RETURN_NONE; for (i = 0; i < sk_GENERAL_NAME_num(dp->distpoint->name.fullname); i++) { GENERAL_NAME *gn = sk_GENERAL_NAME_value(dp->distpoint->name.fullname, i); if (gn->type == GEN_URI) n++; } if (((result = PyTuple_New(n)) == NULL)) goto error; n = 0; for (i = 0; i < sk_GENERAL_NAME_num(dp->distpoint->name.fullname); i++) { GENERAL_NAME *gn = sk_GENERAL_NAME_value(dp->distpoint->name.fullname, i); if (gn->type == GEN_URI) { uri = (char *) ASN1_STRING_data(gn->d.uniformResourceIdentifier); if ((obj = PyString_FromString(uri)) == NULL) goto error; PyTuple_SET_ITEM(result, n++, obj); } } sk_DIST_POINT_pop_free(ext, DIST_POINT_free); return result; error: sk_DIST_POINT_pop_free(ext, DIST_POINT_free); Py_XDECREF(result); return NULL; } static char x509_object_set_crldp__doc__[] = "Set CRLDP values for this certificate.\n" "\n" "Argument is a iterable which returns distributionPoint fullName URIs.\n" ; static PyObject * x509_object_set_crldp(x509_object *self, PyObject *args) { CRL_DIST_POINTS *ext = NULL; PyObject *fullNames = NULL; PyObject *iterator = NULL; PyObject *item = NULL; DIST_POINT *dp = NULL; GENERAL_NAME *gn = NULL; Py_ssize_t urilen; char *uri; int ok = 0; ENTERING(x509_object_set_crldp); if (!PyArg_ParseTuple(args, "O", &fullNames)) goto error; if ((ext = sk_DIST_POINT_new_null()) == NULL || (dp = DIST_POINT_new()) == NULL || (dp->distpoint = DIST_POINT_NAME_new()) == NULL || (dp->distpoint->name.fullname = sk_GENERAL_NAME_new_null()) == NULL) lose_no_memory(); dp->distpoint->type = 0; if ((iterator = PyObject_GetIter(fullNames)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if (PyString_AsStringAndSize(item, &uri, &urilen) < 0) goto error; if ((gn = GENERAL_NAME_new()) == NULL || (gn->d.uniformResourceIdentifier = ASN1_IA5STRING_new()) == NULL || !ASN1_OCTET_STRING_set(gn->d.uniformResourceIdentifier, (unsigned char *) uri, urilen)) lose_no_memory(); gn->type = GEN_URI; if (!sk_GENERAL_NAME_push(dp->distpoint->name.fullname, gn)) lose_no_memory(); gn = NULL; Py_XDECREF(item); item = NULL; } Py_XDECREF(iterator); iterator = NULL; if (!sk_DIST_POINT_push(ext, dp)) lose_no_memory(); dp = NULL; if (!X509_add1_ext_i2d(self->x509, NID_crl_distribution_points, ext, 0, X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add CRLDP extension to certificate"); ok = 1; error: sk_DIST_POINT_pop_free(ext, DIST_POINT_free); DIST_POINT_free(dp); GENERAL_NAME_free(gn); Py_XDECREF(item); Py_XDECREF(iterator); if (ok) Py_RETURN_NONE; else return NULL; } static char x509_object_get_certificate_policies__doc__[] = "Get Certificate Policies values for this certificate.\n" "\n" "If this certificate has no Certificate Policies extension, this method\n" "returns None.\n" "\n" "Otherwise, this method returns a sequence of Object Identifiers.\n" "\n" "Policy qualifiers, if any, are ignored.\n" ; static PyObject * x509_object_get_certificate_policies(x509_object *self) { CERTIFICATEPOLICIES *ext = NULL; PyObject *result = NULL; PyObject *obj; int i; ENTERING(x509_object_get_certificate_policies); if ((ext = X509_get_ext_d2i(self->x509, NID_certificate_policies, NULL, NULL)) == NULL) Py_RETURN_NONE; if (((result = PyTuple_New(sk_POLICYINFO_num(ext))) == NULL)) goto error; for (i = 0; i < sk_POLICYINFO_num(ext); i++) { POLICYINFO *p = sk_POLICYINFO_value(ext, i); if ((obj = ASN1_OBJECT_to_PyString(p->policyid)) == NULL) goto error; PyTuple_SET_ITEM(result, i, obj); } sk_POLICYINFO_pop_free(ext, POLICYINFO_free); return result; error: sk_POLICYINFO_pop_free(ext, POLICYINFO_free); Py_XDECREF(result); return NULL; } static char x509_object_set_certificate_policies__doc__[] = "Set Certificate Policies for this certificate.\n" "\n" "Argument is a iterable which returns policy OIDs.\n" "\n" "Policy qualifier are not supported.\n" "\n" "The extension will be marked as critical, since there's not much point\n" "in using this extension without making it critical.\n" ; static PyObject * x509_object_set_certificate_policies(x509_object *self, PyObject *args) { CERTIFICATEPOLICIES *ext = NULL; PyObject *policies = NULL; PyObject *iterator = NULL; POLICYINFO *pol = NULL; PyObject *item = NULL; const char *oid; int ok = 0; ENTERING(x509_object_set_certificate_policies); if (!PyArg_ParseTuple(args, "O", &policies)) goto error; if ((ext = sk_POLICYINFO_new_null()) == NULL) lose_no_memory(); if ((iterator = PyObject_GetIter(policies)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if ((oid = PyString_AsString(item)) == NULL) goto error; if ((pol = POLICYINFO_new()) == NULL) lose_no_memory(); if ((pol->policyid = OBJ_txt2obj(oid, 1)) == NULL) lose("Couldn't parse OID"); if (!sk_POLICYINFO_push(ext, pol)) lose_no_memory(); pol = NULL; Py_XDECREF(item); item = NULL; } Py_XDECREF(iterator); iterator = NULL; if (!X509_add1_ext_i2d(self->x509, NID_certificate_policies, ext, 1, X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add CERTIFICATE_POLICIES extension to certificate"); ok = 1; error: POLICYINFO_free(pol); sk_POLICYINFO_pop_free(ext, POLICYINFO_free); Py_XDECREF(item); Py_XDECREF(iterator); if (ok) Py_RETURN_NONE; else return NULL; } static char x509_object_pprint__doc__[] = "Return a pretty-printed rendition of this certificate.\n" ; static PyObject * x509_object_pprint(x509_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(x509_object_pprint); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!X509_print(bio, self->x509)) lose_openssl_error("Unable to pretty-print certificate"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static struct PyMethodDef x509_object_methods[] = { Define_Method(pemWrite, x509_object_pem_write, METH_NOARGS), Define_Method(derWrite, x509_object_der_write, METH_NOARGS), Define_Method(sign, x509_object_sign, METH_VARARGS), Define_Method(getPublicKey, x509_object_get_public_key, METH_NOARGS), Define_Method(setPublicKey, x509_object_set_public_key, METH_VARARGS), Define_Method(getVersion, x509_object_get_version, METH_NOARGS), Define_Method(setVersion, x509_object_set_version, METH_VARARGS), Define_Method(getSerial, x509_object_get_serial, METH_NOARGS), Define_Method(setSerial, x509_object_set_serial, METH_VARARGS), Define_Method(getIssuer, x509_object_get_issuer, METH_VARARGS), Define_Method(setIssuer, x509_object_set_issuer, METH_VARARGS), Define_Method(getSubject, x509_object_get_subject, METH_VARARGS), Define_Method(setSubject, x509_object_set_subject, METH_VARARGS), Define_Method(getNotBefore, x509_object_get_not_before, METH_NOARGS), Define_Method(getNotAfter, x509_object_get_not_after, METH_NOARGS), Define_Method(setNotAfter, x509_object_set_not_after, METH_VARARGS), Define_Method(setNotBefore, x509_object_set_not_before, METH_VARARGS), Define_Method(clearExtensions, x509_object_clear_extensions, METH_NOARGS), Define_Method(pprint, x509_object_pprint, METH_NOARGS), Define_Method(getSKI, x509_object_get_ski, METH_NOARGS), Define_Method(setSKI, x509_object_set_ski, METH_VARARGS), Define_Method(getAKI, x509_object_get_aki, METH_NOARGS), Define_Method(setAKI, x509_object_set_aki, METH_VARARGS), Define_Method(getKeyUsage, x509_object_get_key_usage, METH_NOARGS), Define_Method(setKeyUsage, x509_object_set_key_usage, METH_VARARGS), Define_Method(getEKU, x509_object_get_eku, METH_NOARGS), Define_Method(setEKU, x509_object_set_eku, METH_VARARGS), Define_Method(getRFC3779, x509_object_get_rfc3779, METH_NOARGS), Define_Method(setRFC3779, x509_object_set_rfc3779, METH_KEYWORDS), Define_Method(getBasicConstraints, x509_object_get_basic_constraints, METH_NOARGS), Define_Method(setBasicConstraints, x509_object_set_basic_constraints, METH_VARARGS), Define_Method(getSIA, x509_object_get_sia, METH_NOARGS), Define_Method(setSIA, x509_object_set_sia, METH_KEYWORDS), Define_Method(getAIA, x509_object_get_aia, METH_NOARGS), Define_Method(setAIA, x509_object_set_aia, METH_VARARGS), Define_Method(getCRLDP, x509_object_get_crldp, METH_NOARGS), Define_Method(setCRLDP, x509_object_set_crldp, METH_VARARGS), Define_Method(getCertificatePolicies, x509_object_get_certificate_policies, METH_NOARGS), Define_Method(setCertificatePolicies, x509_object_set_certificate_policies, METH_VARARGS), Define_Method(getIssuerHash, x509_object_get_issuer_hash, METH_NOARGS), Define_Method(getSubjectHash, x509_object_get_subject_hash, METH_NOARGS), Define_Class_Method(pemRead, x509_object_pem_read, METH_VARARGS), Define_Class_Method(pemReadFile, x509_object_pem_read_file, METH_VARARGS), Define_Class_Method(derRead, x509_object_der_read, METH_VARARGS), Define_Class_Method(derReadFile, x509_object_der_read_file, METH_VARARGS), {NULL} }; static char POW_X509_Type__doc__[] = "This class represents an X.509v3 certificate.\n" ; static PyTypeObject POW_X509_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.X509", /* tp_name */ sizeof(x509_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)x509_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_X509_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ x509_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ x509_object_new, /* tp_new */ }; /* * X509Store object. */ static PyObject * x509_store_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { x509_store_object *self = NULL; ENTERING(x509_store_object_new); if ((self = (x509_store_object *) type->tp_alloc(type, 0)) == NULL) goto error; if ((self->store = X509_STORE_new()) == NULL) lose_no_memory(); self->ctxclass = (PyObject *) &POW_X509StoreCTX_Type; Py_XINCREF(self->ctxclass); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static void x509_store_object_dealloc(x509_store_object *self) { ENTERING(x509_store_object_dealloc); X509_STORE_free(self->store); Py_XDECREF(self->ctxclass); self->ob_type->tp_free((PyObject*) self); } static char x509_store_object_add_trust__doc__[] = "Add a trusted certificate to this certificate store object.\n" "\n" "The \"certificate\" parameter should be an instance of the X509 class.\n" ; static PyObject * x509_store_object_add_trust(x509_store_object *self, PyObject *args) { x509_object *x509 = NULL; ENTERING(x509_store_object_add_trust); if (!PyArg_ParseTuple(args, "O!", &POW_X509_Type, &x509)) goto error; X509_STORE_add_cert(self->store, x509->x509); Py_RETURN_NONE; error: return NULL; } static char x509_store_object_add_crl__doc__[] = "Add a CRL to this certificate store object.\n" "\n" "The \"crl\" parameter should be an instance of the CRL class.\n" ; static PyObject * x509_store_object_add_crl(x509_store_object *self, PyObject *args) { crl_object *crl = NULL; ENTERING(x509_store_object_add_crl); if (!PyArg_ParseTuple(args, "O!", &POW_CRL_Type, &crl)) goto error; X509_STORE_add_crl(self->store, crl->crl); Py_RETURN_NONE; error: return NULL; } static char x509_store_object_set_flags__doc__[] = "Set validation flags for this X509Store.\n" "\n" "Argument is an integer containing bit flags to set.\n" ; static PyObject * x509_store_object_set_flags (x509_store_object *self, PyObject *args) { unsigned long flags; if (!PyArg_ParseTuple(args, "k", &flags)) goto error; if (!X509_VERIFY_PARAM_set_flags(self->store->param, flags)) lose_openssl_error("X509_VERIFY_PARAM_set_flags() failed"); Py_RETURN_NONE; error: return NULL; } static char x509_store_object_clear_flags__doc__[] = "Clear validation flags for this X509Store.\n" "\n" "Argument is an integer containing bit flags to clear.\n" ; static PyObject * x509_store_object_clear_flags (x509_store_object *self, PyObject *args) { unsigned long flags; if (!PyArg_ParseTuple(args, "k", &flags)) goto error; if (!X509_VERIFY_PARAM_clear_flags(self->store->param, flags)) lose_openssl_error("X509_VERIFY_PARAM_clear_flags() failed"); Py_RETURN_NONE; error: return NULL; } static char x509_store_object_set_context_class__doc__[] = "Set validation context class factory for this X509Store.\n" "\n" "This must be a callable object which takes one argument, an X509Store,\n" "and returns a subclass of X509StoreCTX. The callable can be a class\n" "object but need not be, so long as calling it returns an instance of an\n" "appropriate class. The default is X509StoreCTX.\n" ; static PyObject * x509_store_object_set_context_class (x509_store_object *self, PyObject *args) { PyObject *ctxclass = (PyObject *) &POW_X509StoreCTX_Type; if (!PyArg_ParseTuple(args, "|O", &ctxclass)) goto error; if (!PyCallable_Check(ctxclass)) lose("Context class must be callable"); Py_XDECREF(self->ctxclass); self->ctxclass = ctxclass; Py_XINCREF(self->ctxclass); Py_RETURN_NONE; error: return NULL; } static char x509_store_object_verify__doc__[] = "Verify an X509 certificate object using this certificate store.\n" "\n" "Optional second argument is an iterable that supplies untrusted certificates\n" "to be considered when building a chain to the trust anchor.\n" "\n" "This method returns an instance of the store's verification context class.\n" ; static PyObject * x509_store_object_verify(x509_store_object *self, PyObject *args) { x509_store_ctx_object *ctx = NULL; STACK_OF(X509) *stack = NULL; x509_object *x509 = NULL; PyObject *chain = Py_None; int ok; if (!PyArg_ParseTuple(args, "O!|O", &POW_X509_Type, &x509, &chain)) goto error; if ((ctx = (x509_store_ctx_object *) PyObject_CallFunctionObjArgs(self->ctxclass, self, NULL)) == NULL) goto error; if (!POW_X509StoreCTX_Check(ctx)) lose_type_error("Returned context is not a X509StoreCTX"); if (ctx->ctx == NULL) lose("Uninitialized X509StoreCTX"); if (chain != Py_None && (stack = x509_helper_iterable_to_stack(chain)) == NULL) goto error; Py_XINCREF(x509); Py_XINCREF(chain); X509_STORE_CTX_set_cert(ctx->ctx, x509->x509); X509_STORE_CTX_set_chain(ctx->ctx, stack); ok = X509_verify_cert(ctx->ctx); X509_STORE_CTX_set_chain(ctx->ctx, NULL); X509_STORE_CTX_set_cert(ctx->ctx, NULL); Py_XDECREF(chain); Py_XDECREF(x509); sk_X509_free(stack); if (PyErr_Occurred()) goto error; if (ok < 0) lose_openssl_error("X509_verify_cert() raised an exception"); return (PyObject *) ctx; error: /* fall through */ Py_XDECREF(ctx); return NULL; } static struct PyMethodDef x509_store_object_methods[] = { Define_Method(addTrust, x509_store_object_add_trust, METH_VARARGS), Define_Method(addCrl, x509_store_object_add_crl, METH_VARARGS), Define_Method(setContextClass,x509_store_object_set_context_class, METH_VARARGS), Define_Method(setFlags, x509_store_object_set_flags, METH_VARARGS), Define_Method(clearFlags, x509_store_object_clear_flags, METH_VARARGS), Define_Method(verify, x509_store_object_verify, METH_VARARGS), {NULL} }; static char POW_X509Store_Type__doc__[] = "This class holds the OpenSSL certificate store objects used in CMS\n" "and certificate verification.\n" ; static PyTypeObject POW_X509Store_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.X509Store", /* tp_name */ sizeof(x509_store_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)x509_store_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_X509Store_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ x509_store_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ x509_store_object_new, /* tp_new */ }; /* * X509StoreCTX object. */ static int x509_store_ctx_object_verify_cb(int ok, X509_STORE_CTX *ctx) { static char method_name[] = "verify_callback"; PyObject *self = X509_STORE_CTX_get_ex_data(ctx, x509_store_ctx_ex_data_idx); PyObject *result = NULL; if (self == NULL || !PyObject_HasAttrString(self, method_name)) return ok; if ((result = PyObject_CallMethod(self, method_name, "i", ok)) == NULL) return -1; ok = PyObject_IsTrue(result); Py_XDECREF(result); return ok; } static PyObject * x509_store_ctx_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { x509_store_ctx_object *self = NULL; ENTERING(x509_store_ctx_object_new); if ((self = (x509_store_ctx_object *) type->tp_alloc(type, 0)) == NULL) goto error; self->ctx = NULL; self->store = NULL; return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static int x509_store_ctx_object_init(x509_store_ctx_object *self, PyObject *args, GCC_UNUSED PyObject *kwds) { x509_store_object *store = NULL; if (!PyArg_ParseTuple(args, "|O!", &POW_X509Store_Type, &store)) goto error; if ((self->ctx = X509_STORE_CTX_new()) == NULL) lose_no_memory(); if (!X509_STORE_CTX_init(self->ctx, store ? store->store : NULL, NULL, NULL)) lose_openssl_error("Couldn't initialize X509_STORE_CTX"); if (!X509_STORE_CTX_set_ex_data(self->ctx, x509_store_ctx_ex_data_idx, self)) lose_openssl_error("Couldn't set X509_STORE_CTX ex_data"); Py_XDECREF(self->store); self->store = store; Py_XINCREF(self->store); X509_VERIFY_PARAM_set_flags(self->ctx->param, X509_V_FLAG_X509_STRICT); X509_STORE_CTX_set_verify_cb(self->ctx, x509_store_ctx_object_verify_cb); return 0; error: return -1; } static void x509_store_ctx_object_dealloc(x509_store_ctx_object *self) { ENTERING(x509_store_ctx_object_dealloc); X509_STORE_CTX_free(self->ctx); Py_XDECREF(self->store); self->ob_type->tp_free((PyObject*) self); } static PyObject * x509_store_ctx_object_get_store (x509_store_ctx_object *self, GCC_UNUSED void *closure) { return Py_BuildValue("O", self->store == NULL ? Py_None : (PyObject *) self->store); } static char x509_store_ctx_object_get_error__doc__[] = "Extract verification error code from this X509StoreCTX.\n" ; static PyObject* x509_store_ctx_object_get_error (x509_store_ctx_object *self) { return Py_BuildValue("i", X509_STORE_CTX_get_error(self->ctx)); } static char x509_store_ctx_object_get_error_string__doc__[] = "Extract verification error string from this X509StoreCTX.\n" ; static PyObject* x509_store_ctx_object_get_error_string (x509_store_ctx_object *self) { return Py_BuildValue("s", X509_verify_cert_error_string(X509_STORE_CTX_get_error(self->ctx))); } static char x509_store_ctx_object_get_error_depth__doc__[] = "Extract verification error depth from this X509StoreCTX.\n" ; static PyObject* x509_store_ctx_object_get_error_depth (x509_store_ctx_object *self) { return Py_BuildValue("i", X509_STORE_CTX_get_error_depth(self->ctx)); } static char x509_store_ctx_object_get_current_certificate__doc__[] = "Extract the certificate which caused the current validation error,\n" "or None if no certificate is relevant.\n" ; static PyObject * x509_store_ctx_object_get_current_certificate (x509_store_ctx_object *self) { X509 *x = X509_STORE_CTX_get_current_cert(self->ctx); x509_object *obj = NULL; if (x == NULL) Py_RETURN_NONE; if ((x = X509_dup(x)) == NULL) lose_no_memory(); if ((obj = x509_object_new_helper(NULL, x)) == NULL) goto error; return (PyObject *) obj; error: Py_XDECREF(obj); X509_free(x); return NULL; } static char x509_store_ctx_object_get_chain__doc__[] = "Extract certificate chain from X509StoreCTX. If validation\n" "completed succesfully, this is the complete validation chain;\n" "otherwise, the returned chain may be invalid or incomplete.\n" ; static PyObject * x509_store_ctx_object_get_chain (x509_store_ctx_object *self) { STACK_OF(X509) *chain = NULL; PyObject *result = NULL; if ((chain = X509_STORE_CTX_get1_chain(self->ctx)) == NULL) lose_openssl_error("X509_STORE_CTX_get1_chain() failed"); result = stack_to_tuple_helper(CHECKED_PTR_OF(STACK_OF(X509), chain), stack_to_tuple_helper_get_x509); error: /* fall through */ sk_X509_pop_free(chain, X509_free); return result; } /* * For some reason, there are no methods for the policy mechanism for * X509_STORE, only for X509_STORE_CTX. Presumably we can whack these * anyway using the X509_VERIFY_PARAM_*() calls, the question is * whether there's a good reason for this omission. * * For the moment, I'm just going to leave the policy stuff * unimplemented, until we figure out whether it belongs in X509Store * or X509StoreCTX. */ #define IMPLEMENT_X509StoreCTX_POLICY 0 #if IMPLEMENT_X509StoreCTX_POLICY static char x509_store_ctx_object_set_policy__doc__[] = "Set this X509StoreCTX to require a specified certificate policy.\n" ; static PyObject* x509_store_ctx_object_set_policy (x509_store_ctx_object *self, PyObject *args) { ASN1_OBJECT *policy = NULL; char *oid = NULL; if (!PyArg_ParseTuple(args, "s", &oid)) goto error; if ((policy = OBJ_txt2obj(oid, 1)) == NULL) lose_openssl_error("Couldn't parse OID"); if (!X509_VERIFY_PARAM_set_flags(self->ctx->param, X509_V_FLAG_POLICY_CHECK | X509_V_FLAG_EXPLICIT_POLICY)) lose_openssl_error("Couldn't set policy flags"); if (!X509_VERIFY_PARAM_add0_policy(self->ctx->param, policy)) lose_openssl_error("Couldn't set policy"); Py_RETURN_NONE; error: ASN1_OBJECT_free(policy); return NULL; } #endif /* IMPLEMENT_X509StoreCTX_POLICY */ /* * See (omnibus) man page for X509_STORE_CTX_get_error() for other * query methods we might want to expose. Someday we might want to * support X509_V_FLAG_USE_CHECK_TIME too. */ static struct PyMethodDef x509_store_ctx_object_methods[] = { Define_Method(getError, x509_store_ctx_object_get_error, METH_NOARGS), Define_Method(getErrorString, x509_store_ctx_object_get_error_string, METH_NOARGS), Define_Method(getErrorDepth, x509_store_ctx_object_get_error_depth, METH_NOARGS), Define_Method(getCurrentCertificate, x509_store_ctx_object_get_current_certificate, METH_NOARGS), Define_Method(getChain, x509_store_ctx_object_get_chain, METH_NOARGS), #if IMPLEMENT_X509StoreCTX_POLICY Define_Method(setPolicy, x509_store_ctx_object_set_policy, METH_VARARGS), #endif {NULL} }; static PyGetSetDef x509_store_ctx_object_getsetters[] = { {"store", (getter) x509_store_ctx_object_get_store}, {NULL} }; static char POW_X509StoreCTX_Type__doc__[] = "This class holds the state of an OpenSSL certificate verification\n" "operation. Ordinarily, the user will never have cause to instantiate\n" "this class directly, instead, an object of this class will be returned\n" "by X509Store.verify().\n" "\n" "If you need to see OpenSSL's verification callbacks, you can do so\n" "by subclassing X509StoreCTX and attaching your subclass to an X509Store\n" "object using X509Store.setContextClass(). Your subclass should provide\n" "a .verify_callback() method, which should expect to receive one argument:\n" "the integer \"ok\" value passed by OpenSSL's verification callbacks.\n" "\n" "The return value from your .verify_callback() method will be is interpreted\n" "as a boolean value: anything which evaluates to True will be result in a\n" "return value of 1 to OpenSSL, while anything which evaluates to False will\n" "result in a return value of 0 to OpenSSL.\n" ; static PyTypeObject POW_X509StoreCTX_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.X509StoreCTX", /* tp_name */ sizeof(x509_store_ctx_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)x509_store_ctx_object_dealloc,/* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_X509StoreCTX_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ x509_store_ctx_object_methods, /* tp_methods */ 0, /* tp_members */ x509_store_ctx_object_getsetters, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc) x509_store_ctx_object_init, /* tp_init */ 0, /* tp_alloc */ x509_store_ctx_object_new, /* tp_new */ }; /* * CRL object. */ static crl_object * crl_object_new_helper(PyTypeObject *type, X509_CRL *crl) { crl_object *self = NULL; if (type == NULL) type = &POW_CRL_Type; if ((self = (crl_object *) type->tp_alloc(type, 0)) == NULL) return NULL; self->crl = crl; return self; } static PyObject * crl_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { crl_object *self = NULL; X509_CRL *crl = NULL; ENTERING(crl_object_new); if ((crl = X509_CRL_new()) == NULL) lose_no_memory(); if ((self = crl_object_new_helper(type, crl)) == NULL) goto error; return (PyObject *) self; error: X509_CRL_free(crl); return NULL; } static void crl_object_dealloc(crl_object *self) { ENTERING(crl_object_dealloc); X509_CRL_free(self->crl); self->ob_type->tp_free((PyObject*) self); } static PyObject * crl_object_pem_read_helper(PyTypeObject *type, BIO *bio) { crl_object *self; ENTERING(crl_object_pem_read_helper); if ((self = (crl_object *) crl_object_new(type, NULL, NULL)) == NULL) goto error; if (!PEM_read_bio_X509_CRL(bio, &self->crl, NULL, NULL)) lose_openssl_error("Couldn't PEM encoded load CRL"); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static PyObject * crl_object_der_read_helper(PyTypeObject *type, BIO *bio) { crl_object *self; ENTERING(crl_object_der_read_helper); if ((self = (crl_object *) crl_object_new(type, NULL, NULL)) == NULL) goto error; if (!d2i_X509_CRL_bio(bio, &self->crl)) lose_openssl_error("Couldn't load DER encoded CRL"); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static char crl_object_pem_read__doc__[] = "Read a PEM-encoded CRL object from a string.\n" ; static PyObject * crl_object_pem_read(PyTypeObject *type, PyObject *args) { ENTERING(crl_object_pem_read); return read_from_string_helper(crl_object_pem_read_helper, type, args); } static char crl_object_pem_read_file__doc__[] = "Read a PEM-encoded CRL object from a file.\n" ; static PyObject * crl_object_pem_read_file(PyTypeObject *type, PyObject *args) { ENTERING(crl_object_pem_read_file); return read_from_file_helper(crl_object_pem_read_helper, type, args); } static char crl_object_der_read__doc__[] = "Read a DER-encoded CRL object from a string.\n" ; static PyObject * crl_object_der_read(PyTypeObject *type, PyObject *args) { ENTERING(crl_object_der_read); return read_from_string_helper(crl_object_der_read_helper, type, args); } static char crl_object_der_read_file__doc__[] = "Read a DER-encoded CRL object from a file.\n" ; static PyObject * crl_object_der_read_file(PyTypeObject *type, PyObject *args) { ENTERING(crl_object_der_read_file); return read_from_file_helper(crl_object_der_read_helper, type, args); } static X509_EXTENSIONS ** crl_object_extension_helper(crl_object *self) { if (self && self->crl && self->crl->crl) return &self->crl->crl->extensions; PyErr_SetString(PyExc_ValueError, "Can't find X509_EXTENSIONS in CRL object"); return NULL; } static char crl_object_get_version__doc__[] = "Return the version number of this CRL.\n" ; static PyObject * crl_object_get_version(crl_object *self) { ENTERING(crl_object_get_version); return Py_BuildValue("l", X509_CRL_get_version(self->crl)); } static char crl_object_set_version__doc__[] = "Set the version number of this CRL.\n" "\n" "The \"version\" parameter should be a positive integer.\n" ; static PyObject * crl_object_set_version(crl_object *self, PyObject *args) { long version = 0; ENTERING(crl_object_set_version); if (!PyArg_ParseTuple(args, "i", &version)) goto error; if (!X509_CRL_set_version(self->crl, version)) lose_no_memory(); Py_RETURN_NONE; error: return NULL; } static char crl_object_get_issuer__doc__[] = "Return issuer name of this CRL.\n" "\n" "See the \"getIssuer()\" method of the X509 class for more details.\n" ; static PyObject * crl_object_get_issuer(crl_object *self, PyObject *args) { PyObject *result = NULL; int format = OIDNAME_FORMAT; ENTERING(crl_object_get_issuer); if (!PyArg_ParseTuple(args, "|i", &format)) goto error; result = x509_object_helper_get_name(X509_CRL_get_issuer(self->crl), format); error: /* Fall through */ return result; } static char crl_object_set_issuer__doc__[] = "Set this CRL's issuer name.\n" "\n" "See the \"setIssuer()\" method of the X509 class for details.\n" ; static PyObject * crl_object_set_issuer(crl_object *self, PyObject *args) { PyObject *name_sequence = NULL; X509_NAME *name = NULL; ENTERING(crl_object_set_issuer); if (!PyArg_ParseTuple(args, "O", &name_sequence)) goto error; if (!PySequence_Check(name_sequence)) lose_type_error("Inapropriate type"); if ((name = x509_object_helper_set_name(name_sequence)) == NULL) goto error; if (!X509_CRL_set_issuer_name(self->crl, name)) lose_openssl_error("Unable to set issuer name"); X509_NAME_free(name); Py_RETURN_NONE; error: X509_NAME_free(name); return NULL; } static char crl_object_get_issuer_hash__doc__[] = "Return the OpenSSL \"name hash\" for this CRL's issuer name.\n" ; static PyObject * crl_object_get_issuer_hash(crl_object *self) { ENTERING(crl_object_get_issuer_hash); return Py_BuildValue("k", X509_NAME_hash(X509_CRL_get_issuer(self->crl))); } /* * NB: OpenSSL is confused about the name of this field, probably for * backwards compatability with some ancient mistake. What RFC 5280 * calls "thisUpdate", OpenSSL calls "lastUpdate". */ static char crl_object_set_this_update__doc__[] = "Set this CRL's \"thisUpdate\" value.\n" "\n" "The \"time\" parameter should be a datetime object.\n" ; static PyObject * crl_object_set_this_update (crl_object *self, PyObject *args) { PyObject *o = NULL; ASN1_TIME *t = NULL; ENTERING(crl_object_set_this_update); if (!PyArg_ParseTuple(args, "O", &o)) goto error; if ((t = Python_to_ASN1_TIME(o, 1)) == NULL) lose("Couldn't convert thisUpdate string"); if (!X509_CRL_set_lastUpdate(self->crl, t)) /* sic */ lose("Couldn't set thisUpdate"); ASN1_TIME_free(t); Py_RETURN_NONE; error: ASN1_TIME_free(t); return NULL; } static char crl_object_get_this_update__doc__[] = "Return this CRL's \"thisUpdate\" value as a datetime.\n" ; static PyObject * crl_object_get_this_update (crl_object *self) { ENTERING(crl_object_get_this_update); return ASN1_TIME_to_Python(X509_CRL_get_lastUpdate(self->crl)); /* sic */ } static char crl_object_set_next_update__doc__[] = "Set this CRL's \"nextUpdate\" value.\n" "\n" "The \"time\" parameter should be a datetime object.\n" ; static PyObject * crl_object_set_next_update (crl_object *self, PyObject *args) { PyObject *o = NULL; ASN1_TIME *t = NULL; ENTERING(crl_object_set_next_update); if (!PyArg_ParseTuple(args, "O", &o)) goto error; if ((t = Python_to_ASN1_TIME(o, 1)) == NULL) lose("Couldn't parse nextUpdate string"); if (!X509_CRL_set_nextUpdate(self->crl, t)) lose("Couldn't set nextUpdate"); ASN1_TIME_free(t); Py_RETURN_NONE; error: ASN1_TIME_free(t); return NULL; } static char crl_object_get_next_update__doc__[] = "Returns this CRL's \"nextUpdate\" value as a datetime.\n" ; static PyObject * crl_object_get_next_update (crl_object *self) { ENTERING(crl_object_get_next_update); return ASN1_TIME_to_Python(X509_CRL_get_nextUpdate(self->crl)); } static char crl_object_add_revocations__doc__[] = "This method adds a collection of revocations to this CRL.\n" "\n" "The \"iterable\" parameter should be an iterable object which returns\n" "two-element sequences. The first element of each pair should be the\n" "revoked serial number (an integer), the second element should be the\n" "revocation date (a datetime object).\n" ; static PyObject * crl_object_add_revocations(crl_object *self, PyObject *args) { PyObject *iterable = NULL; PyObject *iterator = NULL; PyObject *item = NULL; PyObject *fast = NULL; X509_REVOKED *revoked = NULL; ASN1_INTEGER *serial = NULL; ASN1_TIME *date = NULL; int ok = 0; ENTERING(crl_object_add_revocations); if (!PyArg_ParseTuple(args, "O", &iterable) || (iterator = PyObject_GetIter(iterable)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if ((fast = PySequence_Fast(item, "Revocation entry must be a sequence")) == NULL) goto error; if (PySequence_Fast_GET_SIZE(fast) != 2) lose_type_error("Revocation entry must be two-element sequence"); if ((serial = PyLong_to_ASN1_INTEGER(PySequence_Fast_GET_ITEM(fast, 0))) == NULL || (date = Python_to_ASN1_TIME(PySequence_Fast_GET_ITEM(fast, 1), 1)) == NULL) goto error; if ((revoked = X509_REVOKED_new()) == NULL || !X509_REVOKED_set_serialNumber(revoked, serial) || !X509_REVOKED_set_revocationDate(revoked, date)) lose_no_memory(); ASN1_INTEGER_free(serial); serial = NULL; ASN1_TIME_free(date); date = NULL; if (!X509_CRL_add0_revoked(self->crl, revoked)) lose_no_memory(); revoked = NULL; Py_XDECREF(item); Py_XDECREF(fast); item = fast = NULL; } if (!X509_CRL_sort(self->crl)) lose_openssl_error("Couldn't sort CRL"); ok = 1; error: Py_XDECREF(iterator); Py_XDECREF(item); Py_XDECREF(fast); X509_REVOKED_free(revoked); ASN1_INTEGER_free(serial); ASN1_TIME_free(date); if (ok) Py_RETURN_NONE; else return NULL; } static char crl_object_get_revoked__doc__[] = "Return a sequence of two-element tuples representing the sequence of\n" "revoked certificates listed in this CRL.\n" "\n" "The first element of each pair is the serialNumber of the revoked\n" "certificate, the second element is the revocationDate.\n" ; static PyObject * crl_object_get_revoked(crl_object *self) { STACK_OF(X509_REVOKED) *revoked = NULL; X509_REVOKED *r = NULL; PyObject *result = NULL; PyObject *item = NULL; PyObject *serial = NULL; PyObject *date = NULL; int i; ENTERING(crl_object_get_revoked); if ((revoked = X509_CRL_get_REVOKED(self->crl)) == NULL) lose("Inexplicable NULL revocation list pointer"); if ((result = PyTuple_New(sk_X509_REVOKED_num(revoked))) == NULL) goto error; for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) { r = sk_X509_REVOKED_value(revoked, i); if ((serial = ASN1_INTEGER_to_PyLong(r->serialNumber)) == NULL || (date = ASN1_TIME_to_Python(r->revocationDate)) == NULL || (item = Py_BuildValue("(NN)", serial, date)) == NULL) goto error; PyTuple_SET_ITEM(result, i, item); item = serial = date = NULL; } return result; error: Py_XDECREF(result); Py_XDECREF(item); Py_XDECREF(serial); Py_XDECREF(date); return NULL; } static char crl_object_clear_extensions__doc__[] = "Clear all extensions attached to this CRL.\n" ; static PyObject * crl_object_clear_extensions(crl_object *self) { X509_EXTENSION *ext; ENTERING(crl_object_clear_extensions); while ((ext = X509_CRL_delete_ext(self->crl, 0)) != NULL) X509_EXTENSION_free(ext); Py_RETURN_NONE; } static char crl_object_sign__doc__[] = "Sign this CRL with a private key.\n" "\n" "The \"key\" parameter should be an instance of the Asymmetric class,\n" "containing a private key.\n" "\n" "The optional \"digest\" parameter indicates which digest to compute and\n" "sign, and should be one of the following:\n" "\n" "* MD5_DIGEST\n" "* SHA_DIGEST\n" "* SHA1_DIGEST\n" "* SHA256_DIGEST\n" "* SHA384_DIGEST\n" "* SHA512_DIGEST\n" "\n" "The default digest algorithm is SHA-256.\n" ; static PyObject * crl_object_sign(crl_object *self, PyObject *args) { asymmetric_object *asym; int digest_type = SHA256_DIGEST; const EVP_MD *digest_method = NULL; ENTERING(crl_object_sign); if (!PyArg_ParseTuple(args, "O!|i", &POW_Asymmetric_Type, &asym, &digest_type)) goto error; if ((digest_method = evp_digest_factory(digest_type)) == NULL) lose("Unsupported digest algorithm"); if (!X509_CRL_sign(self->crl, asym->pkey, digest_method)) lose_openssl_error("Couldn't sign CRL"); Py_RETURN_NONE; error: return NULL; } static char crl_object_verify__doc__[] = "Verify this CRL's signature.\n" "\n" "The check is performed using OpenSSL's X509_CRL_verify() function.\n" "\n" "The \"key\" parameter should be an instance of the Asymmetric class\n" "containing the public key of the purported signer.\n" ; static PyObject * crl_object_verify(crl_object *self, PyObject *args) { asymmetric_object *asym; ENTERING(crl_object_verify); if (!PyArg_ParseTuple(args, "O!", &POW_Asymmetric_Type, &asym)) goto error; return PyBool_FromLong(X509_CRL_verify(self->crl, asym->pkey)); error: return NULL; } static char crl_object_pem_write__doc__[] = "Return the PEM encoding of this CRL, as a string.\n" ; static PyObject * crl_object_pem_write(crl_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(crl_object_pem_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!PEM_write_bio_X509_CRL(bio, self->crl)) lose_openssl_error("Unable to write CRL"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char crl_object_der_write__doc__[] = "Return the DER encoding of this CRL, as a string.\n" ; static PyObject * crl_object_der_write(crl_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(crl_object_der_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!i2d_X509_CRL_bio(bio, self->crl)) lose_openssl_error("Unable to write CRL"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char crl_object_get_aki__doc__[] = EXTENSION_GET_AKI__DOC__ ; static PyObject * crl_object_get_aki(crl_object *self) { return extension_get_aki(crl_object_extension_helper(self)); } static char crl_object_set_aki__doc__[] = EXTENSION_SET_AKI__DOC__ ; static PyObject * crl_object_set_aki(crl_object *self, PyObject *args) { return extension_set_aki(crl_object_extension_helper(self), args); } static char crl_object_get_crl_number__doc__[] = "Return the CRL Number extension value from this CRL, an integer.\n" ; static PyObject * crl_object_get_crl_number(crl_object *self) { ASN1_INTEGER *ext = X509_CRL_get_ext_d2i(self->crl, NID_crl_number, NULL, NULL); PyObject *result = NULL; ENTERING(crl_object_get_crl_number); if (ext == NULL) Py_RETURN_NONE; result = Py_BuildValue("N", ASN1_INTEGER_to_PyLong(ext)); ASN1_INTEGER_free(ext); return result; } static char crl_object_set_crl_number__doc__[] = "Set the CRL Number extension value in this CRL.\n" "\n" "The \"number\" parameter should be an integer.\n" ; static PyObject * crl_object_set_crl_number(crl_object *self, PyObject *args) { ASN1_INTEGER *ext = NULL; PyObject *crl_number = NULL; ENTERING(crl_object_set_crl_number); if (!PyArg_ParseTuple(args, "O", &crl_number) || (ext = PyLong_to_ASN1_INTEGER(crl_number)) == NULL) goto error; if (!X509_CRL_add1_ext_i2d(self->crl, NID_crl_number, ext, 0, X509V3_ADD_REPLACE)) lose_openssl_error("Couldn't add CRL Number extension to CRL"); ASN1_INTEGER_free(ext); Py_RETURN_NONE; error: ASN1_INTEGER_free(ext); return NULL; } static char crl_object_pprint__doc__[] = "Return a pretty-printed rendition of this CRL.\n" ; static PyObject * crl_object_pprint(crl_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(crl_object_pprint); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!X509_CRL_print(bio, self->crl)) lose_openssl_error("Unable to pretty-print CRL"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static struct PyMethodDef crl_object_methods[] = { Define_Method(sign, crl_object_sign, METH_VARARGS), Define_Method(verify, crl_object_verify, METH_VARARGS), Define_Method(getVersion, crl_object_get_version, METH_NOARGS), Define_Method(setVersion, crl_object_set_version, METH_VARARGS), Define_Method(getIssuer, crl_object_get_issuer, METH_VARARGS), Define_Method(setIssuer, crl_object_set_issuer, METH_VARARGS), Define_Method(getThisUpdate, crl_object_get_this_update, METH_NOARGS), Define_Method(setThisUpdate, crl_object_set_this_update, METH_VARARGS), Define_Method(getNextUpdate, crl_object_get_next_update, METH_NOARGS), Define_Method(setNextUpdate, crl_object_set_next_update, METH_VARARGS), Define_Method(getRevoked, crl_object_get_revoked, METH_NOARGS), Define_Method(addRevocations, crl_object_add_revocations, METH_VARARGS), Define_Method(clearExtensions, crl_object_clear_extensions, METH_NOARGS), Define_Method(pemWrite, crl_object_pem_write, METH_NOARGS), Define_Method(derWrite, crl_object_der_write, METH_NOARGS), Define_Method(pprint, crl_object_pprint, METH_NOARGS), Define_Method(getAKI, crl_object_get_aki, METH_NOARGS), Define_Method(setAKI, crl_object_set_aki, METH_VARARGS), Define_Method(getCRLNumber, crl_object_get_crl_number, METH_NOARGS), Define_Method(setCRLNumber, crl_object_set_crl_number, METH_VARARGS), Define_Method(getIssuerHash, crl_object_get_issuer_hash, METH_NOARGS), Define_Class_Method(pemRead, crl_object_pem_read, METH_VARARGS), Define_Class_Method(pemReadFile, crl_object_pem_read_file, METH_VARARGS), Define_Class_Method(derRead, crl_object_der_read, METH_VARARGS), Define_Class_Method(derReadFile, crl_object_der_read_file, METH_VARARGS), {NULL} }; static char POW_CRL_Type__doc__[] = "Container for OpenSSL's X509 CRL management facilities.\n" ; static PyTypeObject POW_CRL_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.CRL", /* tp_name */ sizeof(crl_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)crl_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_CRL_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ crl_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ crl_object_new, /* tp_new */ }; /* * Asymmetric object. */ static PyObject * asymmetric_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { asymmetric_object *self = NULL; ENTERING(asymmetric_object_new); if ((self = (asymmetric_object *) type->tp_alloc(type, 0)) == NULL) goto error; self->pkey = NULL; return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static int asymmetric_object_init(asymmetric_object *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {NULL}; ENTERING(asymmetric_object_init); if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) goto error; /* * We used to take arguments to generate an RSA key, but that's * now in the .generateRSA() class method. */ return 0; error: return -1; } static void asymmetric_object_dealloc(asymmetric_object *self) { ENTERING(asymmetric_object_dealloc); EVP_PKEY_free(self->pkey); self->ob_type->tp_free((PyObject*) self); } static PyObject * asymmetric_object_pem_read_private_helper(PyTypeObject *type, BIO *bio, char *pass) { asymmetric_object *self = NULL; ENTERING(asymmetric_object_pem_read_private_helper); if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL) goto error; if (!PEM_read_bio_PrivateKey(bio, &self->pkey, NULL, pass)) lose_openssl_error("Couldn't load private key"); whack_ec_key_to_namedCurve(self->pkey); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } /* * We can't use the generic read_from_*_helper() functions here * because of optional the PEM password, so we just code the two PEM * read cases for private keys directly. Other than the passphrase, * code is pretty much the same as the generic functions. * * It turns out that OpenSSL is moving away from its old raw PKCS #1.5 * private key format in favor of PKCS #8. This makes sense, but it * leaves us with a minor mess to track. Many OpenSSL functions that * originally expected PKCS #1.5 now also accept PKCS #8, so there's * no tearing hurry about this, but at some point we might want to * switch to writing PKCS #8. It looks like this would be relatively * straightforward: see functions i2d_PKCS8PrivateKey_bio() and * PEM_write_bio_PKCS8PrivateKey(), and note that PKCS #8 supports * encrypted private keys in DER format, so the DER methods should * take a passphrase argument as the PEM methods do. */ static char asymmetric_object_pem_read_private__doc__[] = "Read a PEM-encoded private key from a string.\n" "\n" "Optional second argument is a passphrase for the key.\n" ; static PyObject * asymmetric_object_pem_read_private(PyTypeObject *type, PyObject *args) { PyObject *result = NULL; char *pass = NULL; char *src = NULL; BIO *bio = NULL; Py_ssize_t len = 0; ENTERING(asymmetric_object_pem_read_private); if (!PyArg_ParseTuple(args, "s#|s", &src, &len, &pass)) goto error; if ((bio = BIO_new_mem_buf(src, len)) == NULL) lose_no_memory(); result = asymmetric_object_pem_read_private_helper(type, bio, pass); error: BIO_free(bio); return result; } static char asymmetric_object_pem_read_private_file__doc__[] = "Read a PEM-encoded private key from a file.\n" "\n" "Optional second argument is a passphrase for the key.\n" ; static PyObject * asymmetric_object_pem_read_private_file(PyTypeObject *type, PyObject *args) { const char *filename = NULL; PyObject *result = NULL; char *pass = NULL; BIO *bio = NULL; ENTERING(asymmetric_object_pem_read_private_file); if (!PyArg_ParseTuple(args, "s|s", &filename, &pass)) goto error; if ((bio = BIO_new_file(filename, "rb")) == NULL) lose_openssl_error("Could not open file"); result = asymmetric_object_pem_read_private_helper(type, bio, pass); error: BIO_free(bio); return result; } /* * Used to be only PEM format private keys had passphrases, but with PKCS #8 * that's not really true anymore. We may need to extend the API here to allow * passphrases for DER private keys as well. */ static PyObject * asymmetric_object_der_read_private_helper(PyTypeObject *type, BIO *bio) { asymmetric_object *self = NULL; ENTERING(asymmetric_object_der_read_private_helper); if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL) goto error; if (!d2i_PrivateKey_bio(bio, &self->pkey)) lose_openssl_error("Couldn't load private key"); whack_ec_key_to_namedCurve(self->pkey); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static char asymmetric_object_der_read_private__doc__[] = "Read a DER-encoded private key from a string.\n" ; static PyObject * asymmetric_object_der_read_private(PyTypeObject *type, PyObject *args) { ENTERING(asymmetric_object_der_read_private); return read_from_string_helper(asymmetric_object_der_read_private_helper, type, args); } static char asymmetric_object_der_read_private_file__doc__[] = "Read a DER-encoded private key from a file.\n" ; static PyObject * asymmetric_object_der_read_private_file(PyTypeObject *type, PyObject *args) { ENTERING(asymmetric_object_der_read_private_file); return read_from_file_helper(asymmetric_object_der_read_private_helper, type, args); } static PyObject * asymmetric_object_pem_read_public_helper(PyTypeObject *type, BIO *bio) { asymmetric_object *self = NULL; ENTERING(asymmetric_object_pem_read_public_helper); if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL) goto error; if (!PEM_read_bio_PUBKEY(bio, &self->pkey, NULL, NULL)) lose_openssl_error("Couldn't load public key"); whack_ec_key_to_namedCurve(self->pkey); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static PyObject * asymmetric_object_der_read_public_helper(PyTypeObject *type, BIO *bio) { asymmetric_object *self = NULL; ENTERING(asymmetric_object_der_read_public_helper); if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL) goto error; if (!d2i_PUBKEY_bio(bio, &self->pkey)) lose_openssl_error("Couldn't load public key"); whack_ec_key_to_namedCurve(self->pkey); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static char asymmetric_object_pem_read_public__doc__[] = "Read a PEM-encoded public key from a string.\n" ; static PyObject * asymmetric_object_pem_read_public(PyTypeObject *type, PyObject *args) { ENTERING(asymmetric_object_pem_read_public); return read_from_string_helper(asymmetric_object_pem_read_public_helper, type, args); } static char asymmetric_object_pem_read_public_file__doc__[] = "Read a PEM-encoded public key from a file.\n" ; static PyObject * asymmetric_object_pem_read_public_file(PyTypeObject *type, PyObject *args) { ENTERING(asymmetric_object_pem_read_public_file); return read_from_file_helper(asymmetric_object_pem_read_public_helper, type, args); } static char asymmetric_object_der_read_public__doc__[] = "Read a DER-encoded public key from a string.\n" ; static PyObject * asymmetric_object_der_read_public(PyTypeObject *type, PyObject *args) { ENTERING(asymmetric_object_der_read_public); return read_from_string_helper(asymmetric_object_der_read_public_helper, type, args); } static char asymmetric_object_der_read_public_file__doc__[] = "Read a DER-encoded public key from a file.\n" ; static PyObject * asymmetric_object_der_read_public_file(PyTypeObject *type, PyObject *args) { ENTERING(asymmetric_object_der_read_public_file); return read_from_file_helper(asymmetric_object_der_read_public_helper, type, args); } static char asymmetric_object_pem_write_private__doc__[] = "Return the PEM encoding of an \"Asymmetric\" private key.\n" "\n" "This method takes an optional parameter \"passphrase\" which, if\n" "specified, will be used to encrypt the private key with AES-256-CBC.\n" "\n" "If you don't specify a passphrase, the key will not be encrypted.\n" ; static PyObject * asymmetric_object_pem_write_private(asymmetric_object *self, PyObject *args) { PyObject *result = NULL; char *passphrase = NULL; const EVP_CIPHER *evp_method = NULL; BIO *bio = NULL; ENTERING(asymmetric_object_pem_write_private); if (!PyArg_ParseTuple(args, "|s", &passphrase)) goto error; if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (passphrase) evp_method = EVP_aes_256_cbc(); if (!PEM_write_bio_PrivateKey(bio, self->pkey, evp_method, NULL, 0, NULL, passphrase)) lose_openssl_error("Unable to write key"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char asymmetric_object_pem_write_public__doc__[] = "Return the PEM encoding of an \"Asymmetric\" public key.\n" ; static PyObject * asymmetric_object_pem_write_public(asymmetric_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(asymmetric_object_pem_write_public); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!PEM_write_bio_PUBKEY(bio, self->pkey)) lose_openssl_error("Unable to write key"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char asymmetric_object_der_write_private__doc__[] = "Return the DER encoding of an \"Asymmetric\" private key.\n" ; static PyObject * asymmetric_object_der_write_private(asymmetric_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(asymmetric_object_der_write_private); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!i2d_PrivateKey_bio(bio, self->pkey)) lose_openssl_error("Unable to write private key"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char asymmetric_object_der_write_public__doc__[] = "Return the DER encoding of an \"Asymmetric\" public key.\n" ; static PyObject * asymmetric_object_der_write_public(asymmetric_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(asymmetric_object_der_write_public); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!i2d_PUBKEY_bio(bio, self->pkey)) lose_openssl_error("Unable to write public key"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char asymmetric_object_generate_rsa__doc__[] = "Generate a new RSA keypair.\n" "\n" "Optional argument key_size is the desired key size, in bits;\n" "if not specified, the default is 2048." ; static PyObject * asymmetric_object_generate_rsa(PyTypeObject *type, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"key_size", NULL}; asymmetric_object *self = NULL; EVP_PKEY_CTX *ctx = NULL; int key_size = 2048; int ok = 0; ENTERING(asymmetric_object_generate_rsa); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &key_size)) goto error; if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL) goto error; /* * Explictly setting RSA_F4 would be tedious, as it requires messing * about with bignums, and F4 is the default, so we leave it alone. * In case this ever changes, the required sequence would be: * BN_new(), BN_set_word(), EVP_PKEY_CTX_set_rsa_keygen_pubexp(), * BN_free(). */ if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL)) == NULL || EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_size) <= 0 || EVP_PKEY_keygen(ctx, &self->pkey) <= 0) lose_openssl_error("Couldn't generate new RSA key"); ok = 1; error: EVP_PKEY_CTX_free(ctx); if (ok) return (PyObject *) self; Py_XDECREF(self); return NULL; } static char asymmetric_object_generate_from_params__doc__[] = "Generate a new keypair using an AsymmetricParams object.\n" ; static PyObject * asymmetric_object_generate_from_params(PyTypeObject *type, PyObject *args) { asymmetric_params_object *params = NULL; asymmetric_object *self = NULL; EVP_PKEY_CTX *ctx = NULL; int ok = 0; ENTERING(asymmetric_object_generate_from_params); if (!PyArg_ParseTuple(args, "O!", &POW_AsymmetricParams_Type, ¶ms)) goto error; if ((self = (asymmetric_object *) asymmetric_object_new(type, NULL, NULL)) == NULL) goto error; if ((ctx = EVP_PKEY_CTX_new(params->pkey, NULL)) == NULL || EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &self->pkey) <= 0) lose_openssl_error("Couldn't generate new key"); whack_ec_key_to_namedCurve(self->pkey); ok = 1; error: EVP_PKEY_CTX_free(ctx); if (ok) return (PyObject *) self; Py_XDECREF(self); return NULL; } static char asymmetric_object_calculate_ski__doc__[] = "Calculate SKI value for this key.\n" "\n" "The SKI is the SHA-1 hash of key's SubjectPublicKey value.\n" ; static PyObject * asymmetric_object_calculate_ski(asymmetric_object *self) { PyObject *result = NULL; X509_PUBKEY *pubkey = NULL; unsigned char digest[EVP_MAX_MD_SIZE]; unsigned digest_length; ENTERING(asymmetric_object_calculate_ski); if (!X509_PUBKEY_set(&pubkey, self->pkey)) lose_openssl_error("Couldn't extract public key"); if (!EVP_Digest(pubkey->public_key->data, pubkey->public_key->length, digest, &digest_length, EVP_sha1(), NULL)) lose_openssl_error("Couldn't calculate SHA-1 digest of public key"); result = PyString_FromStringAndSize((char *) digest, digest_length); error: X509_PUBKEY_free(pubkey); return result; } static struct PyMethodDef asymmetric_object_methods[] = { Define_Method(pemWritePrivate, asymmetric_object_pem_write_private, METH_VARARGS), Define_Method(pemWritePublic, asymmetric_object_pem_write_public, METH_NOARGS), Define_Method(derWritePrivate, asymmetric_object_der_write_private, METH_NOARGS), Define_Method(derWritePublic, asymmetric_object_der_write_public, METH_NOARGS), Define_Method(calculateSKI, asymmetric_object_calculate_ski, METH_NOARGS), Define_Class_Method(pemReadPublic, asymmetric_object_pem_read_public, METH_VARARGS), Define_Class_Method(pemReadPublicFile, asymmetric_object_pem_read_public_file, METH_VARARGS), Define_Class_Method(derReadPublic, asymmetric_object_der_read_public, METH_VARARGS), Define_Class_Method(derReadPublicFile, asymmetric_object_der_read_public_file, METH_VARARGS), Define_Class_Method(pemReadPrivate, asymmetric_object_pem_read_private, METH_VARARGS), Define_Class_Method(pemReadPrivateFile, asymmetric_object_pem_read_private_file, METH_VARARGS), Define_Class_Method(derReadPrivate, asymmetric_object_der_read_private, METH_VARARGS), Define_Class_Method(derReadPrivateFile, asymmetric_object_der_read_private_file, METH_VARARGS), Define_Class_Method(generateRSA, asymmetric_object_generate_rsa, METH_KEYWORDS), Define_Class_Method(generateFromParams, asymmetric_object_generate_from_params, METH_VARARGS), {NULL} }; static char POW_Asymmetric_Type__doc__[] = "Container for OpenSSL's EVP_PKEY asymmetric key classes.\n" ; static PyTypeObject POW_Asymmetric_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.Asymmetric", /* tp_name */ sizeof(asymmetric_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)asymmetric_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_Asymmetric_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ asymmetric_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc) asymmetric_object_init, /* tp_init */ 0, /* tp_alloc */ asymmetric_object_new, /* tp_new */ }; /* * AsymmetricParams object. */ static PyObject * asymmetric_params_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { asymmetric_params_object *self = NULL; ENTERING(asymmetric_params_object_new); if ((self = (asymmetric_params_object *) type->tp_alloc(type, 0)) == NULL) goto error; self->pkey = NULL; return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static int asymmetric_params_object_init(asymmetric_params_object *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {NULL}; ENTERING(asymmetric_params_object_init); if (!PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist)) goto error; return 0; error: return -1; } static void asymmetric_params_object_dealloc(asymmetric_params_object *self) { ENTERING(asymmetric_params_object_dealloc); EVP_PKEY_free(self->pkey); self->ob_type->tp_free((PyObject*) self); } static PyObject * asymmetric_params_object_pem_read_helper(PyTypeObject *type, BIO *bio) { asymmetric_params_object *self = NULL; ENTERING(asymmetric_params_object_pem_read_helper); if ((self = (asymmetric_params_object *) asymmetric_params_object_new(type, NULL, NULL)) == NULL) goto error; if (!PEM_read_bio_Parameters(bio, &self->pkey)) lose_openssl_error("Couldn't load PEM encoded key parameters"); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static char asymmetric_params_object_pem_read__doc__[] = "Read PEM-encoded key parameters from a string.\n" ; static PyObject * asymmetric_params_object_pem_read(PyTypeObject *type, PyObject *args) { ENTERING(asymmetric_params_object_pem_read); return read_from_string_helper(asymmetric_params_object_pem_read_helper, type, args); } static char asymmetric_params_object_pem_read_file__doc__[] = "Read PEM-encoded key parameters from a file.\n" ; static PyObject * asymmetric_params_object_pem_read_file(PyTypeObject *type, PyObject *args) { ENTERING(asymmetric_params_object_pem_read_file); return read_from_file_helper(asymmetric_params_object_pem_read_helper, type, args); } static char asymmetric_params_object_pem_write__doc__[] = "Return the PEM encoding of this set of key parameters, as a string.\n" ; static PyObject * asymmetric_params_object_pem_write(asymmetric_params_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(asymmetric_params_object_pem_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (PEM_write_bio_Parameters(bio, self->pkey) <= 0) lose_openssl_error("Unable to write key parameters"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char asymmetric_params_object_generate_ec__doc__[] = "Generate a new set of EC parameters.\n" "\n" "Optional argument curve is a numeric code representing the curve to use;\n" "if not specified, the default is P-256." ; static PyObject * asymmetric_params_object_generate_ec(PyTypeObject *type, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"curve", NULL}; asymmetric_params_object *self = NULL; EVP_PKEY_CTX *ctx = NULL; int curve = NID_X9_62_prime256v1; int ok = 0; ENTERING(asymmetric_params_object_generate_ec); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &curve)) goto error; if ((self = (asymmetric_params_object *) asymmetric_params_object_new(type, NULL, NULL)) == NULL) goto error; if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) == NULL || EVP_PKEY_paramgen_init(ctx) <= 0 || EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, curve) <= 0 || EVP_PKEY_paramgen(ctx, &self->pkey) <= 0) lose_openssl_error("Couldn't generate key parameters"); ok = 1; error: EVP_PKEY_CTX_free(ctx); if (ok) return (PyObject *) self; Py_XDECREF(self); return NULL; } static char asymmetric_params_object_generate_dh__doc__[] = "Generate a new set of DH parameters.\n" "\n" "Optional argument prime_length is length of the DH prime parameter\n" "to use, in bits; if not specified, the default is 2048 bits.\n" "\n" "Be warned that generating DH parameters with a 2048-bit prime may\n" "take a ridiculously long time.\n" ; static PyObject * asymmetric_params_object_generate_dh(PyTypeObject *type, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"prime_length", NULL}; asymmetric_params_object *self = NULL; EVP_PKEY_CTX *ctx = NULL; int prime_length = 2048; int ok = 0; ENTERING(asymmetric_params_object_generate_dh); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &prime_length)) goto error; if ((self = (asymmetric_params_object *) asymmetric_params_object_new(type, NULL, NULL)) == NULL) goto error; if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL)) == NULL || EVP_PKEY_paramgen_init(ctx) <= 0 || EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, prime_length) <= 0 || EVP_PKEY_paramgen(ctx, &self->pkey) <= 0) lose_openssl_error("Couldn't generate key parameters"); ok = 1; error: EVP_PKEY_CTX_free(ctx); if (ok) return (PyObject *) self; Py_XDECREF(self); return NULL; } static char asymmetric_params_object_generate_dsa__doc__[] = "Generate a new set of DSA parameters.\n" "\n" "Optional argument key_length is the length of the key to generate, in bits;\n" "if not specified, the default is 2048 bits." ; static PyObject * asymmetric_params_object_generate_dsa(PyTypeObject *type, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"key_length", NULL}; asymmetric_params_object *self = NULL; EVP_PKEY_CTX *ctx = NULL; int key_length = 2048; int ok = 0; ENTERING(asymmetric_params_object_generate_dsa); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &key_length)) goto error; if ((self = (asymmetric_params_object *) asymmetric_params_object_new(type, NULL, NULL)) == NULL) goto error; if ((ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL)) == NULL || EVP_PKEY_paramgen_init(ctx) <= 0 || EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, key_length) <= 0 || EVP_PKEY_paramgen(ctx, &self->pkey) <= 0) lose_openssl_error("Couldn't generate key parameters"); ok = 1; error: EVP_PKEY_CTX_free(ctx); if (ok) return (PyObject *) self; Py_XDECREF(self); return NULL; } static struct PyMethodDef asymmetric_params_object_methods[] = { Define_Method(pemWrite, asymmetric_params_object_pem_write, METH_NOARGS), Define_Class_Method(pemRead, asymmetric_params_object_pem_read, METH_VARARGS), Define_Class_Method(pemReadFile, asymmetric_params_object_pem_read_file, METH_VARARGS), Define_Class_Method(generateEC, asymmetric_params_object_generate_ec, METH_KEYWORDS), Define_Class_Method(generateDH, asymmetric_params_object_generate_dh, METH_KEYWORDS), Define_Class_Method(generateDSA, asymmetric_params_object_generate_dsa, METH_KEYWORDS), {NULL} }; static char POW_AsymmetricParams_Type__doc__[] = "Container for OpenSSL's EVP_PKEY asymmetric key parameter classes.\n" ; static PyTypeObject POW_AsymmetricParams_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.AsymmetricParams", /* tp_name */ sizeof(asymmetric_params_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)asymmetric_params_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_AsymmetricParams_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ asymmetric_params_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc) asymmetric_params_object_init, /* tp_init */ 0, /* tp_alloc */ asymmetric_params_object_new, /* tp_new */ }; /* * Digest object. */ static PyObject * digest_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { digest_object *self = NULL; ENTERING(digest_object_new); if ((self = (digest_object *) type->tp_alloc(type, 0)) == NULL) goto error; self->digest_type = 0; return (PyObject *) self; error: return NULL; } static int digest_object_init(digest_object *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"digest_type", NULL}; const EVP_MD *digest_method = NULL; int digest_type = 0; ENTERING(digest_object_init); if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &digest_type)) goto error; if ((digest_method = evp_digest_factory(digest_type)) == NULL) lose("Unsupported digest algorithm"); self->digest_type = digest_type; if (!EVP_DigestInit(&self->digest_ctx, digest_method)) lose_openssl_error("Couldn't initialize digest"); return 0; error: return -1; } static void digest_object_dealloc(digest_object *self) { ENTERING(digest_object_dealloc); EVP_MD_CTX_cleanup(&self->digest_ctx); self->ob_type->tp_free((PyObject*) self); } static char digest_object_update__doc__[] = "Add data to this digest.\n" "\n" "the \"data\" parameter should be a string containing the data to be added.\n" ; static PyObject * digest_object_update(digest_object *self, PyObject *args) { char *data = NULL; Py_ssize_t len = 0; ENTERING(digest_object_update); if (!PyArg_ParseTuple(args, "s#", &data, &len)) goto error; if (!EVP_DigestUpdate(&self->digest_ctx, data, len)) lose_openssl_error("EVP_DigestUpdate() failed"); Py_RETURN_NONE; error: return NULL; } static char digest_object_copy__doc__[] = "Return a copy of this Digest object.\n" ; static PyObject * digest_object_copy(digest_object *self) { digest_object *new = NULL; ENTERING(digest_object_copy); if ((new = (digest_object *) digest_object_new(&POW_Digest_Type, NULL, NULL)) == NULL) goto error; new->digest_type = self->digest_type; if (!EVP_MD_CTX_copy(&new->digest_ctx, &self->digest_ctx)) lose_openssl_error("Couldn't copy digest"); return (PyObject*) new; error: Py_XDECREF(new); return NULL; } static char digest_object_digest__doc__[] = "Return the digest of all the data which this Digest object has processed.\n" "\n" "This method can be called at any time and will not effect the internal\n" "state of the Digest object.\n" ; /* * Do we really need to do this copy? Nice general operation, but does * anything we're doing for RPKI care? */ static PyObject * digest_object_digest(digest_object *self) { unsigned char digest_text[EVP_MAX_MD_SIZE]; EVP_MD_CTX ctx; unsigned digest_len = 0; ENTERING(digest_object_digest); if (!EVP_MD_CTX_copy(&ctx, &self->digest_ctx)) lose_openssl_error("Couldn't copy digest"); EVP_DigestFinal(&ctx, digest_text, &digest_len); EVP_MD_CTX_cleanup(&ctx); return Py_BuildValue("s#", digest_text, (Py_ssize_t) digest_len); error: return NULL; } static struct PyMethodDef digest_object_methods[] = { Define_Method(update, digest_object_update, METH_VARARGS), Define_Method(digest, digest_object_digest, METH_NOARGS), Define_Method(copy, digest_object_copy, METH_NOARGS), {NULL} }; static char POW_Digest_Type__doc__[] = "This class provides access to the digest functionality of OpenSSL.\n" "It emulates the digest modules in the Python Standard Library, but\n" "does not currently support the \"hexdigest\" method.\n" "\n" "The constructor takes one parameter, the kind of Digest object to create.\n" "This should be one of the following:\n" "\n" " * MD5_DIGEST\n" " * SHA_DIGEST\n" " * SHA1_DIGEST\n" " * SHA256_DIGEST\n" " * SHA384_DIGEST\n" " * SHA512_DIGEST\n" ; static PyTypeObject POW_Digest_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.Digest", /* tp_name */ sizeof(digest_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)digest_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_Digest_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ digest_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc) digest_object_init, /* tp_init */ 0, /* tp_alloc */ digest_object_new, /* tp_new */ }; /* * CMS object. */ static PyObject * cms_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { cms_object *self; ENTERING(cms_object_new); if ((self = (cms_object *) type->tp_alloc(type, 0)) != NULL) return (PyObject *) self; Py_XDECREF(self); return NULL; } static void cms_object_dealloc(cms_object *self) { ENTERING(cms_object_dealloc); CMS_ContentInfo_free(self->cms); self->ob_type->tp_free((PyObject*) self); } static PyObject * cms_object_pem_read_helper(PyTypeObject *type, BIO *bio) { cms_object *self; ENTERING(cms_object_pem_read_helper); if ((self = (cms_object *) type->tp_new(type, NULL, NULL)) == NULL) goto error; if (!PEM_read_bio_CMS(bio, &self->cms, NULL, NULL)) lose_openssl_error("Couldn't load PEM encoded CMS message"); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static PyObject * cms_object_der_read_helper(PyTypeObject *type, BIO *bio) { cms_object *self; ENTERING(cms_object_der_read_helper); if ((self = (cms_object *) type->tp_new(type, NULL, NULL)) == NULL) goto error; if (!d2i_CMS_bio(bio, &self->cms)) lose_openssl_error("Couldn't load DER encoded CMS message"); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static char cms_object_pem_read__doc__[] = "Read a PEM-encoded CMS object from a string.\n" ; static PyObject * cms_object_pem_read(PyTypeObject *type, PyObject *args) { ENTERING(cms_object_pem_read); return read_from_string_helper(cms_object_pem_read_helper, type, args); } static char cms_object_pem_read_file__doc__[] = "Read a PEM-encoded CMS object from a file.\n" ; static PyObject * cms_object_pem_read_file(PyTypeObject *type, PyObject *args) { ENTERING(cms_object_pem_read_file); return read_from_file_helper(cms_object_pem_read_helper, type, args); } static char cms_object_der_read__doc__[] = "Read a DER-encoded CMS object from a string.\n" ; static PyObject * cms_object_der_read(PyTypeObject *type, PyObject *args) { ENTERING(cms_object_der_read); return read_from_string_helper(cms_object_der_read_helper, type, args); } static char cms_object_der_read_file__doc__[] = "Read a DER-encoded CMS object from a file.\n" ; static PyObject * cms_object_der_read_file(PyTypeObject *type, PyObject *args) { ENTERING(cms_object_der_read_file); return read_from_file_helper(cms_object_der_read_helper, type, args); } static char cms_object_pem_write__doc__[] = "Return the DER encoding of this CMS message.\n" ; static PyObject * cms_object_pem_write(cms_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(cms_object_pem_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!PEM_write_bio_CMS(bio, self->cms)) lose_openssl_error("Unable to write CMS object"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char cms_object_der_write__doc__[] = "Return the DER encoding of this CMS message.\n" ; static PyObject * cms_object_der_write(cms_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(cms_object_der_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!i2d_CMS_bio(bio, self->cms)) lose_openssl_error("Unable to write CMS object"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static int cms_object_sign_helper(cms_object *self, BIO *bio, x509_object *signcert, asymmetric_object *signkey, PyObject *x509_iterable, PyObject *crl_iterable, char *oid, unsigned flags) { STACK_OF(X509) *x509_stack = NULL; ASN1_OBJECT *econtent_type = NULL; CMS_ContentInfo *cms = NULL; PyObject *iterator = NULL; PyObject *item = NULL; int ok = 0; ENTERING(cms_object_sign_helper); assert_no_unhandled_openssl_errors(); flags &= CMS_NOCERTS | CMS_NOATTR; flags |= CMS_BINARY | CMS_NOSMIMECAP | CMS_PARTIAL | CMS_USE_KEYID; if ((x509_stack = x509_helper_iterable_to_stack(x509_iterable)) == NULL) goto error; assert_no_unhandled_openssl_errors(); if (oid && (econtent_type = OBJ_txt2obj(oid, 1)) == NULL) lose_openssl_error("Couldn't parse OID"); assert_no_unhandled_openssl_errors(); if ((cms = CMS_sign(NULL, NULL, x509_stack, bio, flags)) == NULL) lose_openssl_error("Couldn't create CMS message"); assert_no_unhandled_openssl_errors(); if (econtent_type) CMS_set1_eContentType(cms, econtent_type); assert_no_unhandled_openssl_errors(); if (!CMS_add1_signer(cms, signcert->x509, signkey->pkey, EVP_sha256(), flags)) lose_openssl_error("Couldn't sign CMS message"); assert_no_unhandled_openssl_errors(); if (crl_iterable != Py_None) { if ((iterator = PyObject_GetIter(crl_iterable)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if (!POW_CRL_Check(item)) lose_type_error("Inappropriate type"); if (!CMS_add1_crl(cms, ((crl_object *) item)->crl)) lose_openssl_error("Couldn't add CRL to CMS"); assert_no_unhandled_openssl_errors(); Py_XDECREF(item); item = NULL; } } if (!CMS_final(cms, bio, NULL, flags)) lose_openssl_error("Couldn't finalize CMS signatures"); assert_no_unhandled_openssl_errors(); CMS_ContentInfo_free(self->cms); self->cms = cms; cms = NULL; ok = 1; error: /* fall through */ CMS_ContentInfo_free(cms); sk_X509_free(x509_stack); ASN1_OBJECT_free(econtent_type); Py_XDECREF(iterator); Py_XDECREF(item); return ok; } static char cms_object_sign__doc__[] = "Sign this CMS message message with a private key.\n" "\n" "The \"signcert\" parameter should be the certificate against which the\n" "message will eventually be verified, an X509 object.\n" "\n" "The \"key\" parameter should be the private key with which to sign the\n" "message, an Asymmetric object.\n" "\n" "The \"data\" parameter should be the message to be signed, a string.\n" "\n" "The optional \"certs\" parameter should be an iterable supplying X509 objects\n" "to be included in the signed message.\n" "\n" "The optional \"crls\" parameter should be an iterable supplying CRL objects\n" "to be included in the signed message.\n" "\n" "The optional \"eContentType\" parameter should be an Object Identifier\n" "to use as the eContentType value in the signed message.\n" "\n" "The optional \"flags\" parameters should be an integer holding a bitmask,\n" "and can include the following flags:\n" "\n" " * CMS_NOCERTS\n" " * CMS_NOATTR\n" ; static PyObject * cms_object_sign(cms_object *self, PyObject *args) { asymmetric_object *signkey = NULL; x509_object *signcert = NULL; PyObject *x509_iterable = Py_None; PyObject *crl_iterable = Py_None; char *buf = NULL, *oid = NULL; Py_ssize_t len; unsigned flags = 0; BIO *bio = NULL; int ok = 0; ENTERING(cms_object_sign); if (!PyArg_ParseTuple(args, "O!O!s#|OOsI", &POW_X509_Type, &signcert, &POW_Asymmetric_Type, &signkey, &buf, &len, &x509_iterable, &crl_iterable, &oid, &flags)) goto error; assert_no_unhandled_openssl_errors(); if ((bio = BIO_new_mem_buf(buf, len)) == NULL) lose_no_memory(); assert_no_unhandled_openssl_errors(); if (!cms_object_sign_helper(self, bio, signcert, signkey, x509_iterable, crl_iterable, oid, flags)) lose_openssl_error("Couldn't sign CMS object"); assert_no_unhandled_openssl_errors(); ok = 1; error: BIO_free(bio); if (ok) Py_RETURN_NONE; else return NULL; } #define DONT_VERIFY_ANYTHING \ (CMS_NOCRL | \ CMS_NO_SIGNER_CERT_VERIFY | \ CMS_NO_ATTR_VERIFY | \ CMS_NO_CONTENT_VERIFY) static BIO * cms_object_extract_without_verifying_helper(cms_object *self) { BIO *bio = NULL; ENTERING(cms_object_extract_without_verifying_helper); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (CMS_verify(self->cms, NULL, NULL, NULL, bio, DONT_VERIFY_ANYTHING) <= 0) lose_openssl_error("Couldn't parse CMS message"); return bio; error: BIO_free(bio); return NULL; } #undef DONT_VERIFY_ANYTHING #define CMS_OBJECT_VERIFY_HELPER__DOC__ \ "\n" \ "The \"store\" parameter is an X509Store object, the trusted certificate\n" \ "store to use in verification.\n" \ "\n" \ "The optional \"certs\" parameter is a set of certificates to search\n" \ "for the signer's certificate.\n" \ "\n" \ "The optional \"flags\" parameter is an integer of bit flags,\n" \ "containing zero or more of the following:\n" \ "\n" \ " * CMS_NOINTERN\n" \ " * CMS_NOCRL\n" \ " * CMS_NO_SIGNER_CERT_VERIFY\n" \ " * CMS_NO_ATTR_VERIFY\n" \ " * CMS_NO_CONTENT_VERIFY\n" static BIO * cms_object_verify_helper(cms_object *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"store", "certs", "flags", NULL}; x509_store_object *store = NULL; PyObject *certs_iterable = Py_None; STACK_OF(X509) *certs_stack = NULL; unsigned flags = 0, ok = 0; BIO *bio = NULL; ENTERING(cms_object_verify_helper); if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|OI", kwlist, &POW_X509Store_Type, &store, &certs_iterable, &flags)) goto error; if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); assert_no_unhandled_openssl_errors(); flags &= (CMS_NOINTERN | CMS_NOCRL | CMS_NO_SIGNER_CERT_VERIFY | CMS_NO_ATTR_VERIFY | CMS_NO_CONTENT_VERIFY); if (certs_iterable != Py_None && (certs_stack = x509_helper_iterable_to_stack(certs_iterable)) == NULL) goto error; assert_no_unhandled_openssl_errors(); if (CMS_verify(self->cms, certs_stack, store->store, NULL, bio, flags) <= 0) lose_openssl_error("Couldn't verify CMS message"); assert_no_unhandled_openssl_errors(); ok = 1; error: /* fall through */ sk_X509_free(certs_stack); if (ok) return bio; BIO_free(bio); return NULL; } static char cms_object_verify__doc__[] = "Verify this CMS message against a trusted certificate store.\n" "\n" CMS_OBJECT_VERIFY_HELPER__DOC__ "\n" "Return value is the decoded CMS content, as a Python string.\n" ; static PyObject * cms_object_verify(cms_object *self, PyObject *args, PyObject *kwds) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(cms_object_verify); if ((bio = cms_object_verify_helper(self, args, kwds)) != NULL) result = BIO_to_PyString_helper(bio); BIO_free(bio); return result; } static char cms_object_extract_without_verifying__doc__[] = "Extract content from a CMS object without attempting CMS verification.\n" "\n" "NEVER USE THIS METHOD ON AN UNVERIFIED CMS OBJECT!\n" ; static PyObject * cms_object_extract_without_verifying(cms_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(cms_object_extract_without_verifying); if ((bio = cms_object_extract_without_verifying_helper(self)) != NULL) result = BIO_to_PyString_helper(bio); BIO_free(bio); return result; } static char cms_object_eContentType__doc__[] = "Return the eContentType OID of this CMS message.\n" ; static PyObject * cms_object_eContentType(cms_object *self) { const ASN1_OBJECT *oid = NULL; PyObject *result = NULL; ENTERING(cms_object_eContentType); if ((oid = CMS_get0_eContentType(self->cms)) == NULL) lose_openssl_error("Couldn't extract eContentType from CMS message"); assert_no_unhandled_openssl_errors(); result = ASN1_OBJECT_to_PyString(oid); error: return result; } static char cms_object_signingTime__doc__[] = "Return the signingTime of this CMS message.\n" ; static PyObject * cms_object_signingTime(cms_object *self) { PyObject *result = NULL; STACK_OF(CMS_SignerInfo) *sis = NULL; CMS_SignerInfo *si = NULL; X509_ATTRIBUTE *xa = NULL; ASN1_TYPE *so = NULL; int i; ENTERING(cms_object_signingTime); if ((sis = CMS_get0_SignerInfos(self->cms)) == NULL) lose_openssl_error("Couldn't extract signerInfos from CMS message[1]"); if (sk_CMS_SignerInfo_num(sis) != 1) lose_openssl_error("Couldn't extract signerInfos from CMS message[2]"); si = sk_CMS_SignerInfo_value(sis, 0); if ((i = CMS_signed_get_attr_by_NID(si, NID_pkcs9_signingTime, -1)) < 0) lose_openssl_error("Couldn't extract signerInfos from CMS message[3]"); if ((xa = CMS_signed_get_attr(si, i)) == NULL) lose_openssl_error("Couldn't extract signerInfos from CMS message[4]"); if (xa->single) lose("Couldn't extract signerInfos from CMS message[5]"); if (sk_ASN1_TYPE_num(xa->value.set) != 1) lose("Couldn't extract signerInfos from CMS message[6]"); if ((so = sk_ASN1_TYPE_value(xa->value.set, 0)) == NULL) lose("Couldn't extract signerInfos from CMS message[7]"); switch (so->type) { case V_ASN1_UTCTIME: result = ASN1_TIME_to_Python(so->value.utctime); break; case V_ASN1_GENERALIZEDTIME: result = ASN1_TIME_to_Python(so->value.generalizedtime); break; default: lose("Couldn't extract signerInfos from CMS message[8]"); } error: return result; } static char cms_object_pprint__doc__[] = "Return a pretty-printed representation of this CMS message.\n" ; static PyObject * cms_object_pprint(cms_object *self) { BIO *bio = NULL; PyObject *result = NULL; ENTERING(cms_object_pprint); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!CMS_ContentInfo_print_ctx(bio, self->cms, 0, NULL)) lose_openssl_error("Unable to pretty-print CMS object"); result = BIO_to_PyString_helper(bio); error: BIO_free(bio); return result; } static char cms_object_certs__doc__[] = "Return any certificates embedded in this CMS message, as a sequence\n" "of X509 objects. This sequence will be empty if the message wrapper\n" "contains no certificates.\n" ; static PyObject * cms_object_certs(cms_object *self) { STACK_OF(X509) *certs = NULL; PyObject *result = NULL; ENTERING(cms_object_certs); if ((certs = CMS_get1_certs(self->cms)) != NULL) result = stack_to_tuple_helper(CHECKED_PTR_OF(STACK_OF(X509), certs), stack_to_tuple_helper_get_x509); else if (!ERR_peek_error()) result = Py_BuildValue("()"); else lose_openssl_error("Couldn't extract certs from CMS message"); error: /* fall through */ sk_X509_pop_free(certs, X509_free); return result; } static char cms_object_crls__doc__[] = "Return any CRLs embedded in this CMS message, as a sequence of CRL objects.\n" "This sequence will be empty if the message contains no CRLs.\n" ; static PyObject * cms_object_crls(cms_object *self) { STACK_OF(X509_CRL) *crls = NULL; PyObject *result = NULL; ENTERING(cms_object_crls); if ((crls = CMS_get1_crls(self->cms)) != NULL) result = stack_to_tuple_helper(CHECKED_PTR_OF(STACK_OF(X509_CRL), crls), stack_to_tuple_helper_get_crl); else if (!ERR_peek_error()) result = Py_BuildValue("()"); else lose_openssl_error("Couldn't extract CRLs from CMS message"); error: /* fall through */ sk_X509_CRL_pop_free(crls, X509_CRL_free); return result; } static struct PyMethodDef cms_object_methods[] = { Define_Method(pemWrite, cms_object_pem_write, METH_NOARGS), Define_Method(derWrite, cms_object_der_write, METH_NOARGS), Define_Method(sign, cms_object_sign, METH_VARARGS), Define_Method(verify, cms_object_verify, METH_KEYWORDS), Define_Method(extractWithoutVerifying, cms_object_extract_without_verifying, METH_NOARGS), Define_Method(eContentType, cms_object_eContentType, METH_NOARGS), Define_Method(signingTime, cms_object_signingTime, METH_NOARGS), Define_Method(pprint, cms_object_pprint, METH_NOARGS), Define_Method(certs, cms_object_certs, METH_NOARGS), Define_Method(crls, cms_object_crls, METH_NOARGS), Define_Class_Method(pemRead, cms_object_pem_read, METH_VARARGS), Define_Class_Method(pemReadFile, cms_object_pem_read_file, METH_VARARGS), Define_Class_Method(derRead, cms_object_der_read, METH_VARARGS), Define_Class_Method(derReadFile, cms_object_der_read_file, METH_VARARGS), {NULL} }; static char POW_CMS_Type__doc__[] = "Wrapper for OpenSSL's CMS class. At present this only handes signed\n" "objects, as those are the only kind of CMS objects used in RPKI.\n" ; static PyTypeObject POW_CMS_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.CMS", /* tp_name */ sizeof(cms_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)cms_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_CMS_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ cms_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ cms_object_new, /* tp_new */ }; /* * Manifest object. */ static PyObject * manifest_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { manifest_object *self = NULL; ENTERING(manifest_object_new); if ((self = (manifest_object *) cms_object_new(type, args, kwds)) != NULL && (self->manifest = Manifest_new()) != NULL) return (PyObject *) self; Py_XDECREF(self); return NULL; } static void manifest_object_dealloc(manifest_object *self) { ENTERING(manifest_object_dealloc); Manifest_free(self->manifest); cms_object_dealloc(&self->cms); } static char manifest_object_verify__doc__[] = "Verify this manifest against a trusted certificate store.\n" "\n" CMS_OBJECT_VERIFY_HELPER__DOC__ ; static PyObject * manifest_object_verify(manifest_object *self, PyObject *args, PyObject *kwds) { BIO *bio = NULL; int ok = 0; ENTERING(manifest_object_verify); if ((bio = cms_object_verify_helper(&self->cms, args, kwds)) == NULL) goto error; if (!ASN1_item_d2i_bio(ASN1_ITEM_rptr(Manifest), bio, &self->manifest)) lose_openssl_error("Couldn't decode manifest"); ok = 1; error: BIO_free(bio); if (ok) Py_RETURN_NONE; else return NULL; } static char manifest_object_extract_without_verifying__doc__[] = "Extract manifest payload from CMS wrapper without attempting CMS verification.\n" "\n" "NEVER USE THIS METHOD ON AN UNVERIFIED MANIFEST!\n" ; static PyObject * manifest_object_extract_without_verifying(manifest_object *self) { PyObject *result = NULL; BIO *bio = NULL; int ok = 0; ENTERING(manifest_object_extract_without_verifying); if ((bio = cms_object_extract_without_verifying_helper(&self->cms)) != NULL) result = BIO_to_PyString_helper(bio); if (!ASN1_item_d2i_bio(ASN1_ITEM_rptr(Manifest), bio, &self->manifest)) lose_openssl_error("Couldn't decode manifest"); ok = 1; error: BIO_free(bio); if (ok) Py_RETURN_NONE; else return NULL; } static PyObject * manifest_object_der_read_helper(PyTypeObject *type, BIO *bio) { manifest_object *self; ENTERING(manifest_object_der_read_helper); if ((self = (manifest_object *) cms_object_der_read_helper(type, bio)) != NULL) self->manifest = NULL; return (PyObject *) self; } static char manifest_object_der_read__doc__[] = "Read a DER-encoded manifest object from a string.\n" ; static PyObject * manifest_object_der_read(PyTypeObject *type, PyObject *args) { ENTERING(manifest_object_der_read); return read_from_string_helper(manifest_object_der_read_helper, type, args); } static char manifest_object_der_read_file__doc__[] = "Read a DER-encoded manifest object from a file.\n" ; static PyObject * manifest_object_der_read_file(PyTypeObject *type, PyObject *args) { ENTERING(manifest_object_der_read_file); return read_from_file_helper(manifest_object_der_read_helper, type, args); } static PyObject * manifest_object_pem_read_helper(PyTypeObject *type, BIO *bio) { manifest_object *self; ENTERING(manifest_object_pem_read_helper); if ((self = (manifest_object *) cms_object_pem_read_helper(type, bio)) != NULL) self->manifest = NULL; return (PyObject *) self; } static char manifest_object_pem_read__doc__[] = "Read a PEM-encoded manifest object from a string.\n" ; static PyObject * manifest_object_pem_read(PyTypeObject *type, PyObject *args) { ENTERING(manifest_object_pem_read); return read_from_string_helper(manifest_object_pem_read_helper, type, args); } static char manifest_object_pem_read_file__doc__[] = "Read a PEM-encoded manifest object from a file.\n" ; static PyObject * manifest_object_pem_read_file(PyTypeObject *type, PyObject *args) { ENTERING(manifest_object_pem_read_file); return read_from_file_helper(manifest_object_pem_read_helper, type, args); } static char manifest_object_get_version__doc__[] = "Return the version number of this manifest.\n" ; static PyObject * manifest_object_get_version(manifest_object *self) { ENTERING(manifest_object_get_version); if (self->manifest == NULL) lose_not_verified("Can't report version of unverified manifest"); if (self->manifest->version) return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(self->manifest->version)); else return PyInt_FromLong(0); error: return NULL; } static char manifest_object_set_version__doc__[] = "Set the version number of this manifest.\n" "\n" "The \"version\" parameter should be a non-negative integer.\n" "\n" "As of this writing, zero is both the default and the only defined version.\n" "Attempting to set any version number other than zero will fail, as we\n" "don't understand how to write other versions, by definition.\n" ; static PyObject * manifest_object_set_version(manifest_object *self, PyObject *args) { int version = 0; ENTERING(manifest_object_set_version); if (!PyArg_ParseTuple(args, "|i", &version)) goto error; if (version != 0) lose("RFC 6486 only defines RPKI manifest version zero"); if (self->manifest == NULL) lose_not_verified("Can't set version of unverified manifest"); ASN1_INTEGER_free(self->manifest->version); self->manifest->version = NULL; Py_RETURN_NONE; error: return NULL; } static char manifest_object_get_manifest_number__doc__[] = "Return the manifestNumber of this manifest.\n" ; static PyObject * manifest_object_get_manifest_number(manifest_object *self) { ENTERING(manifest_object_get_manifest_number); if (self->manifest == NULL) lose_not_verified("Can't get manifestNumber of unverified manifest"); return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(self->manifest->manifestNumber)); error: return NULL; } static char manifest_object_set_manifest_number__doc__[] = "Set the manifestNumber of this manifest.\n" "\n" "The \"manifestNumber\" parameter should be a non-negative integer.\n" ; static PyObject * manifest_object_set_manifest_number(manifest_object *self, PyObject *args) { PyObject *manifestNumber = NULL; PyObject *zero = NULL; int ok = 0; ENTERING(manifest_object_set_manifest_number); if (!PyArg_ParseTuple(args, "O", &manifestNumber)) goto error; if ((zero = PyInt_FromLong(0)) == NULL) goto error; switch (PyObject_RichCompareBool(manifestNumber, zero, Py_GE)) { case -1: goto error; case 0: lose("Negative manifest number is not allowed"); } if (self->manifest == NULL) lose_not_verified("Can't set manifestNumber of unverified manifest"); ASN1_INTEGER_free(self->manifest->manifestNumber); if ((self->manifest->manifestNumber = PyLong_to_ASN1_INTEGER(manifestNumber)) == NULL) goto error; ok = 1; error: Py_XDECREF(zero); if (ok) Py_RETURN_NONE; else return NULL; } static char manifest_object_set_this_update__doc__[] = "Set this manifest's \"thisUpdate\" value.\n" "\n" "The \"time\" parameter should be a datetime object.\n" ; static PyObject * manifest_object_set_this_update (manifest_object *self, PyObject *args) { ASN1_TIME *t = NULL; PyObject *o = NULL; ENTERING(manifest_object_set_this_update); if (!PyArg_ParseTuple(args, "O", &o)) goto error; if (self->manifest == NULL) lose_not_verified("Can't set thisUpdate value of unverified manifest"); if ((t = Python_to_ASN1_TIME(o, 0)) == NULL) lose("Couldn't convert thisUpdate string"); ASN1_TIME_free(self->manifest->thisUpdate); self->manifest->thisUpdate = t; Py_RETURN_NONE; error: ASN1_TIME_free(t); return NULL; } static char manifest_object_get_this_update__doc__[] = "Return this manifest's \"thisUpdate\" value as a datetime.\n" ; static PyObject * manifest_object_get_this_update (manifest_object *self) { ENTERING(manifest_object_get_this_update); if (self->manifest == NULL) lose_not_verified("Can't get thisUpdate value of unverified manifest"); return ASN1_TIME_to_Python(self->manifest->thisUpdate); error: return NULL; } static char manifest_object_set_next_update__doc__[] = "Set this manifest's \"nextUpdate\" value.\n" "\n" "The \"time\" parameter should be a datetime object.\n" ; static PyObject * manifest_object_set_next_update (manifest_object *self, PyObject *args) { ASN1_TIME *t = NULL; PyObject *o = NULL; ENTERING(manifest_object_set_next_update); if (!PyArg_ParseTuple(args, "O", &o)) goto error; if (self->manifest == NULL) lose_not_verified("Can't set nextUpdate value of unverified manifest"); if ((t = Python_to_ASN1_TIME(o, 0)) == NULL) lose("Couldn't parse nextUpdate string"); ASN1_TIME_free(self->manifest->nextUpdate); self->manifest->nextUpdate = t; Py_RETURN_NONE; error: ASN1_TIME_free(t); return NULL; } static char manifest_object_get_next_update__doc__[] = "Return this manifest's \"nextUpdate\" value as a datetime.\n" ; static PyObject * manifest_object_get_next_update (manifest_object *self) { ENTERING(manifest_object_get_next_update); if (self->manifest == NULL) lose_not_verified("Can't extract nextUpdate value of unverified manifest"); return ASN1_TIME_to_Python(self->manifest->nextUpdate); error: return NULL; } static char manifest_object_get_algorithm__doc__[] = "Return this manifest's fileHashAlg OID.\n" ; static PyObject * manifest_object_get_algorithm(manifest_object *self) { PyObject *result = NULL; ENTERING(manifest_object_get_algorithm); if (self->manifest == NULL) lose_not_verified("Can't extract algorithm OID of unverified manifest"); result = ASN1_OBJECT_to_PyString(self->manifest->fileHashAlg); error: return result; } static char manifest_object_set_algorithm__doc__[] = "Set this manifest's fileHashAlg OID.\n" ; static PyObject * manifest_object_set_algorithm(manifest_object *self, PyObject *args) { ASN1_OBJECT *oid = NULL; const char *s = NULL; ENTERING(manifest_object_set_algorithm); if (!PyArg_ParseTuple(args, "s", &s)) goto error; if (self->manifest == NULL) lose_not_verified("Can't set algorithm OID for unverified manifest"); if ((oid = OBJ_txt2obj(s, 1)) == NULL) lose_no_memory(); ASN1_OBJECT_free(self->manifest->fileHashAlg); self->manifest->fileHashAlg = oid; Py_RETURN_NONE; error: ASN1_OBJECT_free(oid); return NULL; } static char manifest_object_add_files__doc__[] = "Add a collection of pairs to this manifest.\n" "\n" "The \"iterable\" parameter should be an iterable object supplying\n" "returning two-element sequences; the first element of each sequence\n" "should be the filename (a text string), the second element should be the\n" "hash (a binary string).\n" ; static PyObject * manifest_object_add_files(manifest_object *self, PyObject *args) { PyObject *iterable = NULL; PyObject *iterator = NULL; PyObject *item = NULL; PyObject *fast = NULL; FileAndHash *fah = NULL; char *file = NULL; char *hash = NULL; Py_ssize_t filelen, hashlen; int ok = 0; ENTERING(manifest_object_add_files); if (self->manifest == NULL) lose_not_verified("Can't add files to unverified manifest"); if (!PyArg_ParseTuple(args, "O", &iterable) || (iterator = PyObject_GetIter(iterable)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { if ((fast = PySequence_Fast(item, "FileAndHash entry must be a sequence")) == NULL) goto error; if (PySequence_Fast_GET_SIZE(fast) != 2) lose_type_error("FileAndHash entry must be two-element sequence"); if (PyString_AsStringAndSize(PySequence_Fast_GET_ITEM(fast, 0), &file, &filelen) < 0 || PyString_AsStringAndSize(PySequence_Fast_GET_ITEM(fast, 1), &hash, &hashlen) < 0) goto error; if ((fah = FileAndHash_new()) == NULL || !ASN1_OCTET_STRING_set(fah->file, (unsigned char *) file, filelen) || !ASN1_BIT_STRING_set(fah->hash, (unsigned char *) hash, hashlen) || !sk_FileAndHash_push(self->manifest->fileList, fah)) lose_no_memory(); fah->hash->flags &= ~7; fah->hash->flags |= ASN1_STRING_FLAG_BITS_LEFT; fah = NULL; Py_XDECREF(item); Py_XDECREF(fast); item = fast = NULL; } ok = 1; error: Py_XDECREF(iterator); Py_XDECREF(item); Py_XDECREF(fast); FileAndHash_free(fah); if (ok) Py_RETURN_NONE; else return NULL; } static char manifest_object_get_files__doc__[] = "Return a tuple of pairs representing the contents of\n" "this manifest.\n" ; static PyObject * manifest_object_get_files(manifest_object *self) { PyObject *result = NULL; PyObject *item = NULL; int i; ENTERING(manifest_object_get_files); if (self->manifest == NULL) lose_not_verified("Can't get files from unverified manifest"); if (self->manifest->fileList == NULL) lose("Inexplicable NULL manifest fileList pointer"); if ((result = PyTuple_New(sk_FileAndHash_num(self->manifest->fileList))) == NULL) goto error; for (i = 0; i < sk_FileAndHash_num(self->manifest->fileList); i++) { FileAndHash *fah = sk_FileAndHash_value(self->manifest->fileList, i); item = Py_BuildValue("(s#s#)", ASN1_STRING_data(fah->file), (Py_ssize_t) ASN1_STRING_length(fah->file), ASN1_STRING_data(fah->hash), (Py_ssize_t) ASN1_STRING_length(fah->hash)); if (item == NULL) goto error; PyTuple_SET_ITEM(result, i, item); item = NULL; } return result; error: Py_XDECREF(result); Py_XDECREF(item); return NULL; } static char manifest_object_sign__doc__[] = "Sign this manifest. See the CMS class's .sign() method for details.\n" ; static PyObject * manifest_object_sign(manifest_object *self, PyObject *args) { asymmetric_object *signkey = NULL; x509_object *signcert = NULL; PyObject *x509_iterable = Py_None; PyObject *crl_iterable = Py_None; char *oid = NULL; unsigned flags = 0; BIO *bio = NULL; int ok = 0; ENTERING(manifest_object_sign); if (!PyArg_ParseTuple(args, "O!O!|OOsI", &POW_X509_Type, &signcert, &POW_Asymmetric_Type, &signkey, &x509_iterable, &crl_iterable, &oid, &flags)) goto error; if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); assert_no_unhandled_openssl_errors(); if (!ASN1_item_i2d_bio(ASN1_ITEM_rptr(Manifest), bio, self->manifest)) lose_openssl_error("Couldn't encode manifest"); assert_no_unhandled_openssl_errors(); if (!cms_object_sign_helper(&self->cms, bio, signcert, signkey, x509_iterable, crl_iterable, oid, flags)) lose_openssl_error("Couldn't sign manifest"); assert_no_unhandled_openssl_errors(); ok = 1; error: BIO_free(bio); if (ok) Py_RETURN_NONE; else return NULL; } static struct PyMethodDef manifest_object_methods[] = { Define_Method(getVersion, manifest_object_get_version, METH_NOARGS), Define_Method(setVersion, manifest_object_set_version, METH_VARARGS), Define_Method(getManifestNumber, manifest_object_get_manifest_number, METH_NOARGS), Define_Method(setManifestNumber, manifest_object_set_manifest_number, METH_VARARGS), Define_Method(getThisUpdate, manifest_object_get_this_update, METH_NOARGS), Define_Method(setThisUpdate, manifest_object_set_this_update, METH_VARARGS), Define_Method(getNextUpdate, manifest_object_get_next_update, METH_NOARGS), Define_Method(setNextUpdate, manifest_object_set_next_update, METH_VARARGS), Define_Method(getAlgorithm, manifest_object_get_algorithm, METH_NOARGS), Define_Method(setAlgorithm, manifest_object_set_algorithm, METH_VARARGS), Define_Method(getFiles, manifest_object_get_files, METH_NOARGS), Define_Method(addFiles, manifest_object_add_files, METH_VARARGS), Define_Method(sign, manifest_object_sign, METH_VARARGS), Define_Method(verify, manifest_object_verify, METH_KEYWORDS), Define_Method(extractWithoutVerifying, manifest_object_extract_without_verifying, METH_NOARGS), Define_Class_Method(pemRead, manifest_object_pem_read, METH_VARARGS), Define_Class_Method(pemReadFile, manifest_object_pem_read_file, METH_VARARGS), Define_Class_Method(derRead, manifest_object_der_read, METH_VARARGS), Define_Class_Method(derReadFile, manifest_object_der_read_file, METH_VARARGS), {NULL} }; static char POW_Manifest_Type__doc__[] = "This class provides access to RPKI manifest payload.\n" "Most methods are inherited from or share code with the CMS class.\n" ; static PyTypeObject POW_Manifest_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.Manifest", /* tp_name */ sizeof(manifest_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)manifest_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_Manifest_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ manifest_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &POW_CMS_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ manifest_object_new, /* tp_new */ }; /* * ROA object. */ static PyObject * roa_object_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { roa_object *self = NULL; ENTERING(roa_object_new); if ((self = (roa_object *) cms_object_new(type, args, kwds)) != NULL && (self->roa = ROA_new()) != NULL) return (PyObject *) self; Py_XDECREF(self); return NULL; } static void roa_object_dealloc(roa_object *self) { ENTERING(roa_object_dealloc); ROA_free(self->roa); cms_object_dealloc(&self->cms); } static char roa_object_verify__doc__[] = "Verify this ROA against a trusted certificate store.\n" "\n" CMS_OBJECT_VERIFY_HELPER__DOC__ ; static PyObject * roa_object_verify(roa_object *self, PyObject *args, PyObject *kwds) { BIO *bio = NULL; int ok = 0; ENTERING(roa_object_verify); if ((bio = cms_object_verify_helper(&self->cms, args, kwds)) == NULL) goto error; if (!ASN1_item_d2i_bio(ASN1_ITEM_rptr(ROA), bio, &self->roa)) lose_openssl_error("Couldn't decode ROA"); ok = 1; error: BIO_free(bio); if (ok) Py_RETURN_NONE; else return NULL; } static char roa_object_extract_without_verifying__doc__[] = "Extract ROA payload from CMS wrapper without attempting CMS verification.\n" "\n" "NEVER USE THIS METHOD ON AN UNVERIFIED ROA!\n" ; static PyObject * roa_object_extract_without_verifying(roa_object *self) { PyObject *result = NULL; BIO *bio = NULL; int ok = 0; ENTERING(roa_object_extract_without_verifying); if ((bio = cms_object_extract_without_verifying_helper(&self->cms)) != NULL) result = BIO_to_PyString_helper(bio); if (!ASN1_item_d2i_bio(ASN1_ITEM_rptr(ROA), bio, &self->roa)) lose_openssl_error("Couldn't decode ROA"); ok = 1; error: BIO_free(bio); if (ok) Py_RETURN_NONE; else return NULL; } static PyObject * roa_object_pem_read_helper(PyTypeObject *type, BIO *bio) { roa_object *self; ENTERING(roa_object_pem_read_helper); if ((self = (roa_object *) cms_object_pem_read_helper(type, bio)) != NULL) self->roa = NULL; return (PyObject *) self; } static PyObject * roa_object_der_read_helper(PyTypeObject *type, BIO *bio) { roa_object *self; ENTERING(roa_object_der_read_helper); if ((self = (roa_object *) cms_object_der_read_helper(type, bio)) != NULL) self->roa = NULL; return (PyObject *) self; } static char roa_object_pem_read__doc__[] = "Read a PEM-encoded ROA object from a string.\n" ; static PyObject * roa_object_pem_read(PyTypeObject *type, PyObject *args) { ENTERING(roa_object_pem_read); return read_from_string_helper(roa_object_pem_read_helper, type, args); } static char roa_object_pem_read_file__doc__[] = "Read a PEM-encoded ROA object from a file.\n" ; static PyObject * roa_object_pem_read_file(PyTypeObject *type, PyObject *args) { ENTERING(roa_object_pem_read_file); return read_from_file_helper(roa_object_pem_read_helper, type, args); } static char roa_object_der_read__doc__[] = "Read a DER-encoded ROA object from a string.\n" ; static PyObject * roa_object_der_read(PyTypeObject *type, PyObject *args) { ENTERING(roa_object_der_read); return read_from_string_helper(roa_object_der_read_helper, type, args); } static char roa_object_der_read_file__doc__[] = "Read a DER-encoded ROA object from a file.\n" ; static PyObject * roa_object_der_read_file(PyTypeObject *type, PyObject *args) { ENTERING(roa_object_der_read_file); return read_from_file_helper(roa_object_der_read_helper, type, args); } static char roa_object_get_version__doc__[] = "Return the version number of this ROA.\n" ; static PyObject * roa_object_get_version(roa_object *self) { ENTERING(roa_object_get_version); if (self->roa == NULL) lose_not_verified("Can't get version of unverified ROA"); if (self->roa->version) return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(self->roa->version)); else return PyInt_FromLong(0); error: return NULL; } static char roa_object_set_version__doc__[] = "Set the version number of this ROA.\n" "\n" "The \"version\" parameter should be a non-negative integer.\n" "\n" "As of this writing, zero is both the default and the only defined version.\n" "Attempting to set any version number other than zero will fail, as we\n" "don't understand how to write other versions, by definition.\n" ; static PyObject * roa_object_set_version(roa_object *self, PyObject *args) { int version = 0; ENTERING(roa_object_set_version); if (self->roa == NULL) lose_not_verified("Can't set version of unverified ROA"); if (!PyArg_ParseTuple(args, "|i", &version)) goto error; if (version != 0) lose("RFC 6482 only defines ROA version zero"); ASN1_INTEGER_free(self->roa->version); self->roa->version = NULL; Py_RETURN_NONE; error: return NULL; } static char roa_object_get_asid__doc__[] = "Return the Autonomous System ID of this ROA.\n" ; static PyObject * roa_object_get_asid(roa_object *self) { ENTERING(roa_object_get_asid); if (self->roa == NULL) lose_not_verified("Can't get ASN of unverified ROA"); return Py_BuildValue("N", ASN1_INTEGER_to_PyLong(self->roa->asID)); error: return NULL; } static char roa_object_set_asid__doc__[] = "Sets the Autonomous System ID of this ROA.\n" "\n" "The \"asID\" parameter should be a non-negative integer.\n" ; static PyObject * roa_object_set_asid(roa_object *self, PyObject *args) { PyObject *asID = NULL; PyObject *zero = NULL; int ok = 0; ENTERING(roa_object_set_asid); if (self->roa == NULL) lose_not_verified("Can't set ASN of unverified ROA"); if (!PyArg_ParseTuple(args, "O", &asID)) goto error; if ((zero = PyInt_FromLong(0)) == NULL) goto error; switch (PyObject_RichCompareBool(asID, zero, Py_GE)) { case -1: goto error; case 0: lose("Negative asID is not allowed"); } ASN1_INTEGER_free(self->roa->asID); if ((self->roa->asID = PyLong_to_ASN1_INTEGER(asID)) == NULL) goto error; ok = 1; error: Py_XDECREF(zero); if (ok) Py_RETURN_NONE; else return NULL; } static char roa_object_get_prefixes__doc__[] = "Return this ROA's prefix list. This is a two-element\n" "tuple: the first element is the IPv4 prefix set, the second is the\n" "IPv6 prefix set.\n" "\n" "Each prefix set is either None, if there are no prefixes for this IP\n" "version, or a sequence of three-element tuple representing ROA prefix\n" "entries.\n" "\n" "Each ROA prefix entry consists of the prefix itself (an IPAddress),\n" "the prefix length (an integer), and the maxPrefixLen value, which is\n" "either an integer or None depending on whether the maxPrefixLen value\n" "is set for this prefix.\n" ; static PyObject * roa_object_get_prefixes(roa_object *self) { PyObject *result = NULL; PyObject *ipv4_result = NULL; PyObject *ipv6_result = NULL; PyObject *item = NULL; ipaddress_object *addr = NULL; int i, j; ENTERING(roa_object_get_prefixes); if (self->roa == NULL) lose_not_verified("Can't get prefixes from unverified ROA"); for (i = 0; i < sk_ROAIPAddressFamily_num(self->roa->ipAddrBlocks); i++) { ROAIPAddressFamily *fam = sk_ROAIPAddressFamily_value(self->roa->ipAddrBlocks, i); const unsigned afi = (fam->addressFamily->data[0] << 8) | (fam->addressFamily->data[1]); const ipaddress_version *ip_type = NULL; PyObject **resultp = NULL; switch (afi) { case IANA_AFI_IPV4: resultp = &ipv4_result; ip_type = &ipaddress_version_4; break; case IANA_AFI_IPV6: resultp = &ipv6_result; ip_type = &ipaddress_version_6; break; default: lose_type_error("Unknown AFI"); } if (fam->addressFamily->length > 2) lose_type_error("Unsupported SAFI"); if (*resultp != NULL) lose_type_error("Duplicate ROAIPAddressFamily"); if ((*resultp = PyTuple_New(sk_ROAIPAddress_num(fam->addresses))) == NULL) goto error; for (j = 0; j < sk_ROAIPAddress_num(fam->addresses); j++) { ROAIPAddress *a = sk_ROAIPAddress_value(fam->addresses, j); unsigned prefixlen = ((a->IPAddress)->length * 8 - ((a->IPAddress)->flags & 7)); if ((addr = (ipaddress_object *) POW_IPAddress_Type.tp_alloc(&POW_IPAddress_Type, 0)) == NULL) goto error; addr->type = ip_type; memset(addr->address, 0, sizeof(addr->address)); if ((unsigned) a->IPAddress->length > addr->type->length) lose("ROAIPAddress BIT STRING too long for AFI"); if (a->IPAddress->length > 0) { memcpy(addr->address, a->IPAddress->data, a->IPAddress->length); if ((a->IPAddress->flags & 7) != 0) { unsigned char mask = 0xFF >> (8 - (a->IPAddress->flags & 7)); addr->address[a->IPAddress->length - 1] &= ~mask; } } if (a->maxLength == NULL) item = Py_BuildValue("(NIO)", addr, prefixlen, Py_None); else item = Py_BuildValue("(NIl)", addr, prefixlen, ASN1_INTEGER_get(a->maxLength)); if (item == NULL) goto error; PyTuple_SET_ITEM(*resultp, j, item); item = NULL; addr = NULL; } } result = Py_BuildValue("(OO)", (ipv4_result == NULL ? Py_None : ipv4_result), (ipv6_result == NULL ? Py_None : ipv6_result)); error: /* Fall through */ Py_XDECREF(addr); Py_XDECREF(item); Py_XDECREF(ipv4_result); Py_XDECREF(ipv6_result); return result; } static char roa_object_set_prefixes__doc__[] = "Set this ROA's prefix list.\n" "\n" "This method takes two arguments, \"ipv4\" and \"ipv6\". Each of these\n" "is either None, if no prefixes should be set for this IP version, or\n" "an iterable object returning ROA prefix entries in the same format as\n" "returned by the .getPrefixes() method. The maxPrefixLen value may be\n" "omitted (that is, the ROA prefix entry tuple may be of length two\n" "rather than of length three); this will be taken as equivalent to\n" "specifying a maxPrefixLen value of None.\n" ; static PyObject * roa_object_set_prefixes(roa_object *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"ipv4", "ipv6", NULL}; STACK_OF(ROAIPAddressFamily) *prefixes = NULL; ROAIPAddressFamily *fam = NULL; ROAIPAddress *a = NULL; PyObject *ipv4_arg = Py_None; PyObject *ipv6_arg = Py_None; PyObject *iterator = NULL; PyObject *item = NULL; PyObject *fast = NULL; int ok = 0; int v; ENTERING(roa_object_set_prefixes); if (self->roa == NULL) lose_not_verified("Can't set prefixes of unverified ROA"); if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &ipv4_arg, &ipv6_arg)) goto error; if ((prefixes = sk_ROAIPAddressFamily_new_null()) == NULL) lose_no_memory(); for (v = 0; v < (int) (sizeof(ipaddress_versions)/sizeof(*ipaddress_versions)); v++) { const struct ipaddress_version *ip_type = ipaddress_versions[v]; unsigned char afibuf[2]; PyObject **argp; switch (ip_type->version) { case 4: argp = &ipv4_arg; break; case 6: argp = &ipv6_arg; break; default: continue; } if (*argp == Py_None) continue; afibuf[0] = (ip_type->afi >> 8) & 0xFF; afibuf[1] = (ip_type->afi ) & 0xFF; if ((iterator = PyObject_GetIter(*argp)) == NULL) goto error; while ((item = PyIter_Next(iterator)) != NULL) { unsigned prefixlen, maxprefixlen, bitlen, bytelen; ipaddress_object *addr = NULL; PyObject *maxlenobj = Py_None; if ((fast = PySequence_Fast(item, "ROA prefix must be a sequence")) == NULL) goto error; switch (PySequence_Fast_GET_SIZE(fast)) { case 3: maxlenobj = PySequence_Fast_GET_ITEM(fast, 2); /* Fall through */ case 2: if (!POW_IPAddress_Check(PySequence_Fast_GET_ITEM(fast, 0))) lose_type_error("First element of ROA prefix must be an IPAddress object"); addr = (ipaddress_object *) PySequence_Fast_GET_ITEM(fast, 0); prefixlen = (unsigned) PyInt_AsLong(PySequence_Fast_GET_ITEM(fast, 1)); if (PyErr_Occurred()) goto error; break; default: lose_type_error("ROA prefix must be a two- or three-element sequence"); } if (maxlenobj == Py_None) { maxprefixlen = prefixlen; } else { maxprefixlen = (unsigned) PyInt_AsLong(maxlenobj); if (PyErr_Occurred()) goto error; } if (addr->type != ip_type) lose_type_error("Bad ROA prefix"); if (prefixlen > addr->type->length * 8) lose("Bad prefix length"); if (maxprefixlen > addr->type->length * 8 || maxprefixlen < prefixlen) lose("Bad maxLength value"); bytelen = (prefixlen + 7) / 8; bitlen = prefixlen % 8; if ((a = ROAIPAddress_new()) == NULL || (a->IPAddress == NULL && (a->IPAddress = ASN1_BIT_STRING_new()) == NULL) || !ASN1_BIT_STRING_set(a->IPAddress, addr->address, bytelen)) lose_no_memory(); a->IPAddress->flags &= ~7; a->IPAddress->flags |= ASN1_STRING_FLAG_BITS_LEFT; if (bitlen > 0) { a->IPAddress->data[bytelen - 1] &= ~(0xFF >> bitlen); a->IPAddress->flags |= 8 - bitlen; } if (prefixlen != maxprefixlen && ((a->maxLength = ASN1_INTEGER_new()) == NULL || !ASN1_INTEGER_set(a->maxLength, maxprefixlen))) lose_no_memory(); if (fam == NULL && ((fam = ROAIPAddressFamily_new()) == NULL || !sk_ROAIPAddressFamily_push(prefixes, fam) || !ASN1_OCTET_STRING_set(fam->addressFamily, afibuf, sizeof(afibuf)))) lose_no_memory(); if (!sk_ROAIPAddress_push(fam->addresses, a)) lose_no_memory(); a = NULL; Py_XDECREF(item); Py_XDECREF(fast); item = fast = NULL; } fam = NULL; Py_XDECREF(iterator); iterator = NULL; } sk_ROAIPAddressFamily_pop_free(self->roa->ipAddrBlocks, ROAIPAddressFamily_free); self->roa->ipAddrBlocks = prefixes; prefixes = NULL; ok = 1; error: sk_ROAIPAddressFamily_pop_free(prefixes, ROAIPAddressFamily_free); ROAIPAddressFamily_free(fam); ROAIPAddress_free(a); Py_XDECREF(iterator); Py_XDECREF(item); Py_XDECREF(fast); if (ok) Py_RETURN_NONE; else return NULL; } static char roa_object_sign__doc__[] = "Sign this ROA. See CMS.sign() for details.\n" ; static PyObject * roa_object_sign(roa_object *self, PyObject *args) { asymmetric_object *signkey = NULL; x509_object *signcert = NULL; PyObject *x509_iterable = Py_None; PyObject *crl_iterable = Py_None; char *oid = NULL; unsigned flags = 0; BIO *bio = NULL; int ok = 0; ENTERING(roa_object_sign); if (!PyArg_ParseTuple(args, "O!O!|OOsI", &POW_X509_Type, &signcert, &POW_Asymmetric_Type, &signkey, &x509_iterable, &crl_iterable, &oid, &flags)) goto error; if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); assert_no_unhandled_openssl_errors(); if (!ASN1_item_i2d_bio(ASN1_ITEM_rptr(ROA), bio, self->roa)) lose_openssl_error("Couldn't encode ROA"); assert_no_unhandled_openssl_errors(); if (!cms_object_sign_helper(&self->cms, bio, signcert, signkey, x509_iterable, crl_iterable, oid, flags)) lose_openssl_error("Couldn't sign ROA"); assert_no_unhandled_openssl_errors(); ok = 1; error: BIO_free(bio); if (ok) Py_RETURN_NONE; else return NULL; } static struct PyMethodDef roa_object_methods[] = { Define_Method(getVersion, roa_object_get_version, METH_NOARGS), Define_Method(setVersion, roa_object_set_version, METH_VARARGS), Define_Method(getASID, roa_object_get_asid, METH_NOARGS), Define_Method(setASID, roa_object_set_asid, METH_VARARGS), Define_Method(getPrefixes, roa_object_get_prefixes, METH_NOARGS), Define_Method(setPrefixes, roa_object_set_prefixes, METH_KEYWORDS), Define_Method(sign, roa_object_sign, METH_VARARGS), Define_Method(verify, roa_object_verify, METH_KEYWORDS), Define_Method(extractWithoutVerifying, roa_object_extract_without_verifying, METH_NOARGS), Define_Class_Method(pemRead, roa_object_pem_read, METH_VARARGS), Define_Class_Method(pemReadFile, roa_object_pem_read_file, METH_VARARGS), Define_Class_Method(derRead, roa_object_der_read, METH_VARARGS), Define_Class_Method(derReadFile, roa_object_der_read_file, METH_VARARGS), {NULL} }; static char POW_ROA_Type__doc__[] = "This class provides access to RPKI ROA payload.\n" "Most methods are inherited from or share code with the CMS class.\n" ; static PyTypeObject POW_ROA_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.ROA", /* tp_name */ sizeof(roa_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)roa_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_ROA_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ roa_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ &POW_CMS_Type, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ roa_object_new, /* tp_new */ }; /* * PKCS10 object. */ static PyObject * pkcs10_object_new(PyTypeObject *type, GCC_UNUSED PyObject *args, GCC_UNUSED PyObject *kwds) { pkcs10_object *self; ENTERING(pkcs10_object_new); if ((self = (pkcs10_object *) type->tp_alloc(type, 0)) != NULL && (self->pkcs10 = X509_REQ_new()) != NULL && (self->exts = sk_X509_EXTENSION_new_null()) != NULL) return (PyObject *) self; Py_XDECREF(self); return NULL; } static void pkcs10_object_dealloc(pkcs10_object *self) { ENTERING(pkcs10_object_dealloc); X509_REQ_free(self->pkcs10); sk_X509_EXTENSION_pop_free(self->exts, X509_EXTENSION_free); self->ob_type->tp_free((PyObject*) self); } static PyObject * pkcs10_object_pem_read_helper(PyTypeObject *type, BIO *bio) { pkcs10_object *self = NULL; ENTERING(pkcs10_object_pem_read_helper); assert_no_unhandled_openssl_errors(); if ((self = (pkcs10_object *) pkcs10_object_new(type, NULL, NULL)) == NULL) goto error; assert_no_unhandled_openssl_errors(); if (!PEM_read_bio_X509_REQ(bio, &self->pkcs10, NULL, NULL)) lose_openssl_error("Couldn't load PEM encoded PKCS#10 request"); sk_X509_EXTENSION_pop_free(self->exts, X509_EXTENSION_free); self->exts = X509_REQ_get_extensions(self->pkcs10); assert_no_unhandled_openssl_errors(); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static PyObject * pkcs10_object_der_read_helper(PyTypeObject *type, BIO *bio) { pkcs10_object *self = NULL; ENTERING(pkcs10_object_der_read_helper); assert_no_unhandled_openssl_errors(); if ((self = (pkcs10_object *) pkcs10_object_new(type, NULL, NULL)) == NULL) goto error; assert_no_unhandled_openssl_errors(); if (!d2i_X509_REQ_bio(bio, &self->pkcs10)) lose_openssl_error("Couldn't load DER encoded PKCS#10 request"); sk_X509_EXTENSION_pop_free(self->exts, X509_EXTENSION_free); self->exts = X509_REQ_get_extensions(self->pkcs10); assert_no_unhandled_openssl_errors(); return (PyObject *) self; error: Py_XDECREF(self); return NULL; } static char pkcs10_object_pem_read__doc__[] = "Read a PEM-encoded PKCS#10 object from a string.\n" ; static PyObject * pkcs10_object_pem_read(PyTypeObject *type, PyObject *args) { ENTERING(pkcs10_object_pem_read); return read_from_string_helper(pkcs10_object_pem_read_helper, type, args); } static char pkcs10_object_pem_read_file__doc__[] = "Read a PEM-encoded PKCS#10 object from a file.\n" ; static PyObject * pkcs10_object_pem_read_file(PyTypeObject *type, PyObject *args) { ENTERING(pkcs10_object_pem_read_file); return read_from_file_helper(pkcs10_object_pem_read_helper, type, args); } static char pkcs10_object_der_read__doc__[] = "Read a DER-encoded PKCS#10 object from a string.\n" ; static PyObject * pkcs10_object_der_read(PyTypeObject *type, PyObject *args) { ENTERING(pkcs10_object_der_read); return read_from_string_helper(pkcs10_object_der_read_helper, type, args); } static char pkcs10_object_der_read_file__doc__[] = "Read a DER-encoded PKCS#10 object from a file.\n" ; static PyObject * pkcs10_object_der_read_file(PyTypeObject *type, PyObject *args) { ENTERING(pkcs10_object_der_read_file); return read_from_file_helper(pkcs10_object_der_read_helper, type, args); } static char pkcs10_object_pem_write__doc__[] = "Returns the PEM encoding of this PKCS#10 object.\n" ; static PyObject * pkcs10_object_pem_write(pkcs10_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(pkcs10_object_pem_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!PEM_write_bio_X509_REQ(bio, self->pkcs10)) lose_openssl_error("Unable to write PKCS#10 request"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static char pkcs10_object_der_write__doc__[] = "Return the DER encoding of this PKCS#10 object.\n" ; static PyObject * pkcs10_object_der_write(pkcs10_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(pkcs10_object_der_write); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!i2d_X509_REQ_bio(bio, self->pkcs10)) lose_openssl_error("Unable to write PKCS#10 request"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static X509_EXTENSIONS ** pkcs10_object_extension_helper(pkcs10_object *self) { return &self->exts; } static char pkcs10_object_get_public_key__doc__[] = "Return the public key from this PKCS#10 request, as an Asymmetric\n" "object.\n" ; static PyObject * pkcs10_object_get_public_key(pkcs10_object *self) { PyTypeObject *type = &POW_Asymmetric_Type; asymmetric_object *asym = NULL; ENTERING(pkcs10_object_get_public_key); if ((asym = (asymmetric_object *) type->tp_alloc(type, 0)) == NULL) goto error; if ((asym->pkey = X509_REQ_get_pubkey(self->pkcs10)) == NULL) lose_openssl_error("Couldn't extract public key from PKCS#10 request"); whack_ec_key_to_namedCurve(asym->pkey); return (PyObject *) asym; error: Py_XDECREF(asym); return NULL; } static char pkcs10_object_set_public_key__doc__[] = "Set the public key for this PKCS#10 request.\n" "\n" "The \"key\" parameter should be an instance of the Asymmetric class,\n" "containing a public key.\n" ; static PyObject * pkcs10_object_set_public_key(pkcs10_object *self, PyObject *args) { asymmetric_object *asym; ENTERING(pkcs10_object_set_public_key); if (!PyArg_ParseTuple(args, "O!", &POW_Asymmetric_Type, &asym)) goto error; if (!X509_REQ_set_pubkey(self->pkcs10, asym->pkey)) lose_openssl_error("Couldn't set certificate's PKCS#10 request"); Py_RETURN_NONE; error: return NULL; } static char pkcs10_object_sign__doc__[] = "Sign a PKCS#10 request with a private key.\n" "\n" "The \"key\" parameter should be an instance of the Asymmetric class,\n" "containing a private key.\n" "\n" "The optional \"digest\" parameter indicates which digest to compute and\n" "sign, and should be one of the following:\n" "\n" "* MD5_DIGEST\n" "* SHA_DIGEST\n" "* SHA1_DIGEST\n" "* SHA256_DIGEST\n" "* SHA384_DIGEST\n" "* SHA512_DIGEST\n" "\n" "The default digest algorithm is SHA-256.\n" ; static PyObject * pkcs10_object_sign(pkcs10_object *self, PyObject *args) { asymmetric_object *asym; int loc, digest_type = SHA256_DIGEST; const EVP_MD *digest_method = NULL; ENTERING(pkcs10_object_sign); if (!PyArg_ParseTuple(args, "O!|i", &POW_Asymmetric_Type, &asym, &digest_type)) goto error; if ((digest_method = evp_digest_factory(digest_type)) == NULL) lose("Unsupported digest algorithm"); while ((loc = X509_REQ_get_attr_by_NID(self->pkcs10, NID_ext_req, -1)) >= 0) X509_ATTRIBUTE_free(X509_REQ_delete_attr(self->pkcs10, loc)); if (sk_X509_EXTENSION_num(self->exts) > 0 && !X509_REQ_add_extensions(self->pkcs10, self->exts)) lose_openssl_error("Couldn't add extensions block to PKCS#10 request"); if (!X509_REQ_sign(self->pkcs10, asym->pkey, digest_method)) lose_openssl_error("Couldn't sign PKCS#10 request"); Py_RETURN_NONE; error: return NULL; } static char pkcs10_object_verify__doc__[] = "Verify a PKCS#10 request.\n" "\n" "This calls OpenSSL's X509_REQ_verify() method to check the request's\n" "self-signature.\n" ; static PyObject * pkcs10_object_verify(pkcs10_object *self) { EVP_PKEY *pkey = NULL; int status; ENTERING(pkcs10_object_verify); if ((pkey = X509_REQ_get_pubkey(self->pkcs10)) == NULL) lose_openssl_error("Couldn't extract public key from PKCS#10 for verification"); if ((status = X509_REQ_verify(self->pkcs10, pkey)) < 0) lose_openssl_error("Couldn't verify PKCS#10 signature"); EVP_PKEY_free(pkey); return PyBool_FromLong(status); error: EVP_PKEY_free(pkey); return NULL; } static char pkcs10_object_get_version__doc__[] = "Return the version number of this PKCS#10 request.\n" ; static PyObject * pkcs10_object_get_version(pkcs10_object *self) { ENTERING(pkcs10_object_get_version); return Py_BuildValue("l", X509_REQ_get_version(self->pkcs10)); } static char pkcs10_object_set_version__doc__[] = "Set the version number of this PKCS#10 request.\n" "\n" "The \"version\" parameter should be an integer, but the only defined\n" "value is zero, so this field is optional and defaults to zero.\n" ; static PyObject * pkcs10_object_set_version(pkcs10_object *self, PyObject *args) { long version = 0; ENTERING(pkcs10_object_set_version); if (!PyArg_ParseTuple(args, "|l", &version)) goto error; if (version != 0) lose("RFC 6487 6.1.1 forbids non-zero values for this field"); if (!X509_REQ_set_version(self->pkcs10, version)) lose("Couldn't set certificate version"); Py_RETURN_NONE; error: return NULL; } static char pkcs10_object_get_subject__doc__[] = "Return this PKCS #10 request's subject name.\n" "\n" "See the X509.getIssuer() method for details of the return value and\n" "use of the optional \"format\" parameter.\n" ; static PyObject * pkcs10_object_get_subject(pkcs10_object *self, PyObject *args) { PyObject *result = NULL; int format = OIDNAME_FORMAT; ENTERING(pkcs10_object_get_subject); if (!PyArg_ParseTuple(args, "|i", &format)) goto error; result = x509_object_helper_get_name(X509_REQ_get_subject_name(self->pkcs10), format); error: /* Fall through */ return result; } static char pkcs10_object_set_subject__doc__[] = "Set this PKCS#10 request's subject name.\n" "\n" "The \"name\" parameter should be in the same format as the return\n" "value from the \"getSubject\" method.\n" ; static PyObject * pkcs10_object_set_subject(pkcs10_object *self, PyObject *args) { PyObject *name_sequence = NULL; X509_NAME *name = NULL; ENTERING(pkcs10_object_set_subject); if (!PyArg_ParseTuple(args, "O", &name_sequence)) goto error; if (!PySequence_Check(name_sequence)) lose_type_error("Inapropriate type"); if ((name = x509_object_helper_set_name(name_sequence)) == NULL) goto error; if (!X509_REQ_set_subject_name(self->pkcs10, name)) lose("Unable to set subject name"); X509_NAME_free(name); Py_RETURN_NONE; error: X509_NAME_free(name); return NULL; } static char pkcs10_object_get_key_usage__doc__[] = EXTENSION_GET_KEY_USAGE__DOC__ ; static PyObject * pkcs10_object_get_key_usage(pkcs10_object *self) { return extension_get_key_usage(pkcs10_object_extension_helper(self)); } static char pkcs10_object_set_key_usage__doc__[] = "Set the KeyUsage extension for this PKCS#10 request.\n" "\n" EXTENSION_SET_KEY_USAGE__DOC__ ; static PyObject * pkcs10_object_set_key_usage(pkcs10_object *self, PyObject *args) { return extension_set_key_usage(pkcs10_object_extension_helper(self), args); } static char pkcs10_object_get_eku__doc__[] = EXTENSION_GET_EKU__DOC__ ; static PyObject * pkcs10_object_get_eku(pkcs10_object *self) { return extension_get_eku(pkcs10_object_extension_helper(self)); } static char pkcs10_object_set_eku__doc__[] = "Set the ExtendedKeyUsage extension for this PKCS #10 request.\n" "\n" EXTENSION_SET_EKU__DOC__ ; static PyObject * pkcs10_object_set_eku(pkcs10_object *self, PyObject *args) { return extension_set_eku(pkcs10_object_extension_helper(self), args); } static char pkcs10_object_get_basic_constraints__doc__[] = "Return BasicConstraints value for this PKCS#10 request.\n" "\n" EXTENSION_GET_BASIC_CONSTRAINTS__DOC__ ; static PyObject * pkcs10_object_get_basic_constraints(pkcs10_object *self) { return extension_get_basic_constraints(pkcs10_object_extension_helper(self)); } static char pkcs10_object_set_basic_constraints__doc__[] = "Set BasicConstraints value for this PKCS#10 request.\n" "\n" EXTENSION_SET_BASIC_CONSTRAINTS__DOC__ ; static PyObject * pkcs10_object_set_basic_constraints(pkcs10_object *self, PyObject *args) { return extension_set_basic_constraints(pkcs10_object_extension_helper(self), args); } static char pkcs10_object_get_sia__doc__[] = "Return the SIA values for this PKCS#10 request.\n" "\n" EXTENSION_GET_SIA__DOC__ ; static PyObject * pkcs10_object_get_sia(pkcs10_object *self) { return extension_get_sia(pkcs10_object_extension_helper(self)); } static char pkcs10_object_set_sia__doc__[] = "Set SIA values for this PKCS#10 request.\n" "\n" EXTENSION_SET_SIA__DOC__ ; static PyObject * pkcs10_object_set_sia(pkcs10_object *self, PyObject *args, PyObject *kwds) { return extension_set_sia(pkcs10_object_extension_helper(self), args, kwds); } static char pkcs10_object_get_signature_algorithm__doc__[] = "Return this PKCS #10 reqeuest's signature algorithm OID.\n" ; static PyObject * pkcs10_object_get_signature_algorithm(pkcs10_object *self) { ASN1_OBJECT *oid = NULL; ENTERING(pkcs10_object_get_signature_algorithm); X509_ALGOR_get0(&oid, NULL, NULL, self->pkcs10->sig_alg); return ASN1_OBJECT_to_PyString(oid); } static char pkcs10_object_get_extension_oids__doc__[] = "Return the set of extension OIDs used in this request. This is mostly\n" "useful for enforcing restrictions on what extensions are allowed to be\n" "present, eg, to conform with the RPKI profile.\n" ; static PyObject * pkcs10_object_get_extension_oids(pkcs10_object *self) { PyObject *result = NULL; PyObject *oid = NULL; int i; ENTERING(pkcs10_object_get_extension_oids); if ((result = PyFrozenSet_New(NULL)) == NULL) goto error; for (i = 0; i < sk_X509_EXTENSION_num(self->exts); i++) { X509_EXTENSION *ext = sk_X509_EXTENSION_value(self->exts, i); if ((oid = ASN1_OBJECT_to_PyString(ext->object)) == NULL || PySet_Add(result, oid) < 0) goto error; Py_XDECREF(oid); oid = NULL; } return result; error: Py_XDECREF(result); Py_XDECREF(oid); return NULL; } static char pkcs10_object_pprint__doc__[] = "Return a pretty-printed rendition of this PKCS#10 request.\n" ; static PyObject * pkcs10_object_pprint(pkcs10_object *self) { PyObject *result = NULL; BIO *bio = NULL; ENTERING(pkcs10_object_pprint); if ((bio = BIO_new(BIO_s_mem())) == NULL) lose_no_memory(); if (!X509_REQ_print(bio, self->pkcs10)) lose_openssl_error("Unable to pretty-print PKCS#10 request"); result = BIO_to_PyString_helper(bio); error: /* Fall through */ BIO_free(bio); return result; } static struct PyMethodDef pkcs10_object_methods[] = { Define_Method(pemWrite, pkcs10_object_pem_write, METH_NOARGS), Define_Method(derWrite, pkcs10_object_der_write, METH_NOARGS), Define_Method(sign, pkcs10_object_sign, METH_VARARGS), Define_Method(verify, pkcs10_object_verify, METH_NOARGS), Define_Method(getPublicKey, pkcs10_object_get_public_key, METH_NOARGS), Define_Method(setPublicKey, pkcs10_object_set_public_key, METH_VARARGS), Define_Method(getVersion, pkcs10_object_get_version, METH_NOARGS), Define_Method(setVersion, pkcs10_object_set_version, METH_VARARGS), Define_Method(getSubject, pkcs10_object_get_subject, METH_VARARGS), Define_Method(setSubject, pkcs10_object_set_subject, METH_VARARGS), Define_Method(pprint, pkcs10_object_pprint, METH_NOARGS), Define_Method(getKeyUsage, pkcs10_object_get_key_usage, METH_NOARGS), Define_Method(setKeyUsage, pkcs10_object_set_key_usage, METH_VARARGS), Define_Method(getEKU, pkcs10_object_get_eku, METH_NOARGS), Define_Method(setEKU, pkcs10_object_set_eku, METH_VARARGS), Define_Method(getBasicConstraints, pkcs10_object_get_basic_constraints, METH_NOARGS), Define_Method(setBasicConstraints, pkcs10_object_set_basic_constraints, METH_VARARGS), Define_Method(getSIA, pkcs10_object_get_sia, METH_NOARGS), Define_Method(setSIA, pkcs10_object_set_sia, METH_KEYWORDS), Define_Method(getSignatureAlgorithm, pkcs10_object_get_signature_algorithm, METH_NOARGS), Define_Method(getExtensionOIDs, pkcs10_object_get_extension_oids, METH_NOARGS), Define_Class_Method(pemRead, pkcs10_object_pem_read, METH_VARARGS), Define_Class_Method(pemReadFile, pkcs10_object_pem_read_file, METH_VARARGS), Define_Class_Method(derRead, pkcs10_object_der_read, METH_VARARGS), Define_Class_Method(derReadFile, pkcs10_object_der_read_file, METH_VARARGS), {NULL} }; static char POW_PKCS10_Type__doc__[] = "This class represents a PKCS#10 request.\n" ; static PyTypeObject POW_PKCS10_Type = { PyObject_HEAD_INIT(0) 0, /* ob_size */ "rpki.POW.PKCS10", /* tp_name */ sizeof(pkcs10_object), /* tp_basicsize */ 0, /* tp_itemsize */ (destructor)pkcs10_object_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ POW_PKCS10_Type__doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ pkcs10_object_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ pkcs10_object_new, /* tp_new */ }; /* * Module functions. */ static char pow_module_add_object__doc__[] = "Add new a new object identifier to OpenSSL's internal database.\n" "\n" "The \"oid\" should be an ASN.1 object identifer, represented as a string\n" "in dotted-decimal format.\n" "\n" "The \"shortName\" parameter should be the OpenSSL \"short name\" to use.\n" "\n" "The \"longName\" parameter should be the OpenSSL \"long name\" to use.\n" ; static PyObject * pow_module_add_object(GCC_UNUSED PyObject *self, PyObject *args) { char *oid = NULL, *sn = NULL, *ln = NULL; ENTERING(pow_module_add_object); if (!PyArg_ParseTuple(args, "sss", &oid, &sn, &ln)) goto error; if (!OBJ_create(oid, sn, ln)) lose_openssl_error("Unable to add object"); Py_RETURN_NONE; error: return NULL; } static char pow_module_get_error__doc__[] = "Pop one error off OpenSSL's global error stack and returns it as a string.\n" "\n" "Returns None if the error stack is empty.\n" ; static PyObject * pow_module_get_error(GCC_UNUSED PyObject *self) { unsigned long error = ERR_get_error(); char buf[256]; ENTERING(pow_module_get_error); if (!error) Py_RETURN_NONE; ERR_error_string_n(error, buf, sizeof(buf)); return Py_BuildValue("s", buf); } static char pow_module_clear_error__doc__[] = "Remove all errors from OpenSSL's global error stack.\n" ; static PyObject * pow_module_clear_error(GCC_UNUSED PyObject *self) { ENTERING(pow_module_clear_error); ERR_clear_error(); Py_RETURN_NONE; } static char pow_module_seed__doc__[] = "Add data to OpenSSL's pseudo-random number generator state.\n" "\n" "The \"data\" parameter is the seed to add. Entropy of the data is\n" "assumed to be equal to the length of the data.\n" ; static PyObject * pow_module_seed(GCC_UNUSED PyObject *self, PyObject *args) { char *data = NULL; Py_ssize_t datalen = 0; ENTERING(pow_module_seed); if (!PyArg_ParseTuple(args, "s#", &data, &datalen)) goto error; RAND_seed(data, datalen); Py_RETURN_NONE; error: return NULL; } static char pow_module_add__doc__[] = "Add data to OpenSSL's pseudo-random number generator state.\n" "\n" "The \"data\" parameter is the data to add.\n" "\n" "The \"entropy\" parameter should be an estimate of the number of\n" "random bytes in the data parameter.\n" ; static PyObject * pow_module_add(GCC_UNUSED PyObject *self, PyObject *args) { char *data = NULL; Py_ssize_t datalen = 0; double entropy = 0; ENTERING(pow_module_add); if (!PyArg_ParseTuple(args, "s#d", &data, &datalen, &entropy)) goto error; RAND_add(data, datalen, entropy); Py_RETURN_NONE; error: return NULL; } static char pow_module_write_random_file__doc__[] = "Write the current state of OpenSSL's pseduo-random number generator to\n" "a file.\n" "\n" "The \"filename\" parameter is the name of the file to write.\n" ; static PyObject * pow_module_write_random_file(GCC_UNUSED PyObject *self, PyObject *args) { char *filename = NULL; ENTERING(pow_module_write_random_file); if (!PyArg_ParseTuple(args, "s", &filename)) goto error; if (RAND_write_file(filename) == -1) lose("Couldn't write random file"); Py_RETURN_NONE; error: return NULL; } static char pow_module_read_random_file__doc__[] = "Restore the state of OpenSSLs pseudo-random number generator from\n" "data previously saved to a file.\n" "\n" "The \"filename\" parameter is the name of the file to read.\n" ; static PyObject * pow_module_read_random_file(GCC_UNUSED PyObject *self, PyObject *args) { char *file = NULL; int len = -1; ENTERING(pow_module_read_random_file); if (!PyArg_ParseTuple(args, "s|i", &file, &len)) goto error; if (!RAND_load_file(file, len)) lose("Couldn't load random file"); Py_RETURN_NONE; error: return NULL; } static char pow_module_custom_datetime__doc__[] = "Set constructor callback for customized datetime class.\n" ; static PyObject * pow_module_custom_datetime(GCC_UNUSED PyObject *self, PyObject *args) { PyObject *cb = NULL; ENTERING(pow_module_custom_datetime); if (!PyArg_ParseTuple(args, "O", &cb)) goto error; Py_XINCREF(cb); Py_XDECREF(custom_datetime); custom_datetime = cb; Py_RETURN_NONE; error: return NULL; } static struct PyMethodDef pow_module_methods[] = { Define_Method(getError, pow_module_get_error, METH_NOARGS), Define_Method(clearError, pow_module_clear_error, METH_NOARGS), Define_Method(seed, pow_module_seed, METH_VARARGS), Define_Method(add, pow_module_add, METH_VARARGS), Define_Method(readRandomFile, pow_module_read_random_file, METH_VARARGS), Define_Method(writeRandomFile, pow_module_write_random_file, METH_VARARGS), Define_Method(addObject, pow_module_add_object, METH_VARARGS), Define_Method(customDatetime, pow_module_custom_datetime, METH_VARARGS), {NULL} }; /* * Module initialization. */ void init_POW(void) { PyObject *m = Py_InitModule3("_POW", pow_module_methods, pow_module__doc__); int OpenSSL_ok = 1; /* * Python encourages us to use these functions instead of the ones * in libc, and OpenSSL allows us to do this. The result seems to * work, and, in theory, gives Python's memory allocator a better * idea of how much memory we're really using. Not sure why it * cares, but let's try to be nice about it. * * Note that this must be done BEFORE anything in OpenSSL uses * dynamic memory, and that this will probably fail in horrible ways * without the build-time code (-Bsymbolic, etc) which isolates our * copy of the OpenSSL code from any system shared libraries. * Enough other things already fail in horrible ways without that * isolation that adding one more doesn't make much difference, but * if you tinker with the build script and start seeing nasty * memory-related issues, this might be the cause. */ CRYPTO_set_mem_functions(PyMem_Malloc, PyMem_Realloc, PyMem_Free); /* * Import the DateTime API */ PyDateTime_IMPORT; #define Define_Class(__type__) \ do { \ char *__name__ = strrchr(__type__.tp_name, '.'); \ if (PyType_Ready(&__type__) == 0 && __name__ != NULL) { \ Py_INCREF(&__type__); \ PyModule_AddObject(m, __name__+1, (PyObject *) &__type__); \ } \ } while (0) Define_Class(POW_X509_Type); Define_Class(POW_X509Store_Type); Define_Class(POW_X509StoreCTX_Type); Define_Class(POW_CRL_Type); Define_Class(POW_Asymmetric_Type); Define_Class(POW_AsymmetricParams_Type); Define_Class(POW_Digest_Type); Define_Class(POW_CMS_Type); Define_Class(POW_IPAddress_Type); Define_Class(POW_Manifest_Type); Define_Class(POW_ROA_Type); Define_Class(POW_PKCS10_Type); #undef Define_Class #define Define_Exception(__name__, __parent__) \ PyModule_AddObject(m, #__name__, ((__name__##Object) \ = PyErr_NewException("rpki.POW." #__name__, __parent__, NULL))) Define_Exception(Error, NULL); Define_Exception(OpenSSLError, ErrorObject); Define_Exception(POWError, ErrorObject); Define_Exception(NotVerifiedError, ErrorObject); #undef Define_Exception #define Define_Integer_Constant(__name__) \ PyModule_AddIntConstant(m, #__name__, __name__) /* Object format types */ Define_Integer_Constant(LONGNAME_FORMAT); Define_Integer_Constant(SHORTNAME_FORMAT); Define_Integer_Constant(OIDNAME_FORMAT); /* Message digests */ Define_Integer_Constant(MD5_DIGEST); Define_Integer_Constant(SHA_DIGEST); Define_Integer_Constant(SHA1_DIGEST); Define_Integer_Constant(SHA256_DIGEST); Define_Integer_Constant(SHA384_DIGEST); Define_Integer_Constant(SHA512_DIGEST); /* CMS flags */ Define_Integer_Constant(CMS_NOCERTS); Define_Integer_Constant(CMS_NOATTR); Define_Integer_Constant(CMS_NOINTERN); Define_Integer_Constant(CMS_NOCRL); Define_Integer_Constant(CMS_NO_SIGNER_CERT_VERIFY); Define_Integer_Constant(CMS_NO_ATTR_VERIFY); Define_Integer_Constant(CMS_NO_CONTENT_VERIFY); /* X509 validation flags */ Define_Integer_Constant(X509_V_FLAG_CB_ISSUER_CHECK); Define_Integer_Constant(X509_V_FLAG_USE_CHECK_TIME); Define_Integer_Constant(X509_V_FLAG_CRL_CHECK); Define_Integer_Constant(X509_V_FLAG_CRL_CHECK_ALL); Define_Integer_Constant(X509_V_FLAG_IGNORE_CRITICAL); Define_Integer_Constant(X509_V_FLAG_X509_STRICT); Define_Integer_Constant(X509_V_FLAG_ALLOW_PROXY_CERTS); Define_Integer_Constant(X509_V_FLAG_POLICY_CHECK); Define_Integer_Constant(X509_V_FLAG_EXPLICIT_POLICY); Define_Integer_Constant(X509_V_FLAG_INHIBIT_ANY); Define_Integer_Constant(X509_V_FLAG_INHIBIT_MAP); Define_Integer_Constant(X509_V_FLAG_NOTIFY_POLICY); Define_Integer_Constant(X509_V_FLAG_CHECK_SS_SIGNATURE); /* X509 validation error codes */ Define_Integer_Constant(X509_V_OK); Define_Integer_Constant(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT); Define_Integer_Constant(X509_V_ERR_UNABLE_TO_GET_CRL); Define_Integer_Constant(X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE); Define_Integer_Constant(X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE); Define_Integer_Constant(X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY); Define_Integer_Constant(X509_V_ERR_CERT_SIGNATURE_FAILURE); Define_Integer_Constant(X509_V_ERR_CRL_SIGNATURE_FAILURE); Define_Integer_Constant(X509_V_ERR_CERT_NOT_YET_VALID); Define_Integer_Constant(X509_V_ERR_CERT_HAS_EXPIRED); Define_Integer_Constant(X509_V_ERR_CRL_NOT_YET_VALID); Define_Integer_Constant(X509_V_ERR_CRL_HAS_EXPIRED); Define_Integer_Constant(X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD); Define_Integer_Constant(X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD); Define_Integer_Constant(X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD); Define_Integer_Constant(X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD); Define_Integer_Constant(X509_V_ERR_OUT_OF_MEM); Define_Integer_Constant(X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT); Define_Integer_Constant(X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN); Define_Integer_Constant(X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY); Define_Integer_Constant(X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE); Define_Integer_Constant(X509_V_ERR_CERT_CHAIN_TOO_LONG); Define_Integer_Constant(X509_V_ERR_CERT_REVOKED); Define_Integer_Constant(X509_V_ERR_INVALID_CA); Define_Integer_Constant(X509_V_ERR_PATH_LENGTH_EXCEEDED); Define_Integer_Constant(X509_V_ERR_INVALID_PURPOSE); Define_Integer_Constant(X509_V_ERR_CERT_UNTRUSTED); Define_Integer_Constant(X509_V_ERR_CERT_REJECTED); Define_Integer_Constant(X509_V_ERR_SUBJECT_ISSUER_MISMATCH); Define_Integer_Constant(X509_V_ERR_AKID_SKID_MISMATCH); Define_Integer_Constant(X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH); Define_Integer_Constant(X509_V_ERR_KEYUSAGE_NO_CERTSIGN); Define_Integer_Constant(X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER); Define_Integer_Constant(X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION); Define_Integer_Constant(X509_V_ERR_KEYUSAGE_NO_CRL_SIGN); Define_Integer_Constant(X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION); Define_Integer_Constant(X509_V_ERR_INVALID_NON_CA); Define_Integer_Constant(X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED); Define_Integer_Constant(X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE); Define_Integer_Constant(X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED); Define_Integer_Constant(X509_V_ERR_INVALID_EXTENSION); Define_Integer_Constant(X509_V_ERR_INVALID_POLICY_EXTENSION); Define_Integer_Constant(X509_V_ERR_NO_EXPLICIT_POLICY); Define_Integer_Constant(X509_V_ERR_UNNESTED_RESOURCE); Define_Integer_Constant(X509_V_ERR_APPLICATION_VERIFICATION); /* AsymmetricParam EC curve codes */ Define_Integer_Constant(EC_P256_CURVE); #undef Define_Integer_Constant /* * Initialise library. * * We shouldn't need any of the SSL code or error strings anymore. * * If we cared deeply about avoiding references to symmetric cipher * algorithms and digest algorithms we're not using, we could * replace the call to OpenSSL_add_all_algorithms() with calls to * add just the specific algorithms we use rather than all of them. * For now, don't worry about it. */ OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); OpenSSL_ok &= create_missing_nids(); x509_store_ctx_ex_data_idx = X509_STORE_CTX_get_ex_new_index(0, "x590_store_ctx_object for verify callback", NULL, NULL, NULL); if (PyErr_Occurred() || !OpenSSL_ok) Py_FatalError("Can't initialize module POW"); } /* * Local Variables: * indent-tabs-mode: nil * End: */ ='#n7552'>7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 7854 7855 7856 7857 7858 7859 7860 7861 7862 7863 7864 7865 7866 7867 7868 7869 7870 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 7886 7887 7888 7889 7890 7891 7892 7893 7894 7895 7896 7897 7898 7899 7900 7901 7902 7903 7904 7905 7906 7907 7908 7909 7910 7911 7912 7913 7914 7915 7916 7917 7918 7919 7920 7921 7922 7923 7924 7925 7926 7927 7928 7929 7930 7931 7932 7933 7934 7935 7936 7937 7938 7939 7940 7941 7942 7943 7944 7945 7946 7947 7948 7949 7950 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 7966 7967 7968 7969 7970 7971 7972 7973 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050 8051 8052 8053 8054 8055 8056 8057 8058 8059 8060 8061 8062 8063 8064 8065 8066 8067 8068 8069 8070 8071 8072 8073 8074 8075 8076 8077 8078 8079 8080 8081 8082 8083 8084 8085 8086 8087 8088 8089 8090 8091 8092 8093 8094 8095 8096 8097 8098 8099 8100 8101 8102 8103 8104 8105 8106 8107 8108 8109 8110 8111 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 8127 8128 8129 8130 8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 8145 8146 8147 8148 8149 8150 8151 8152 8153 8154 8155 8156 8157 8158 8159 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185 8186 8187 8188 8189 8190 8191 8192 8193 8194 8195 8196 8197 8198 8199 8200 8201 8202 8203 8204 8205 8206 8207 8208 8209 8210 8211 8212 8213 8214 8215 8216 8217 8218 8219 8220 8221 8222 8223 8224 8225 8226 8227 8228 8229 8230 8231 8232 8233 8234 8235 8236 8237 8238 8239 8240 8241 8242 8243 8244 8245 8246 8247 8248 8249 8250 8251 8252 8253 8254 8255 8256 8257 8258 8259 8260 8261 8262 8263 8264 8265 8266 8267 8268 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 8293 8294 8295 8296 8297 8298 8299 8300 8301 8302 8303 8304 8305 8306 8307 8308 8309 8310 8311 8312 8313 8314 8315 8316 8317 8318 8319 8320 8321 8322 8323 8324 8325 8326 8327 8328 8329 8330 8331 8332 8333 8334 8335 8336 8337 8338 8339 8340 8341 8342 8343 8344 8345 8346 8347 8348 8349 8350 8351 8352 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 8369 8370 8371 8372 8373 8374 8375 8376 8377 8378 8379 8380 8381 8382 8383 8384 8385 8386 8387 8388 8389 8390 8391 8392 8393 8394 8395 8396 8397 8398 8399 8400 8401 8402 8403 8404 8405 8406 8407 8408 8409 8410 8411 8412 8413 8414 8415 8416 8417 8418 8419 8420 8421 8422 8423 8424 8425 8426 8427 8428 8429 8430 8431 8432 8433 8434 8435 8436 8437 8438 8439 8440 8441 8442 8443 8444 8445 8446 8447 8448 8449 8450 8451 8452 8453 8454 8455 8456 8457 8458 8459 8460 8461 8462 8463 8464 8465 8466 8467 8468 8469 8470 8471 8472 8473 8474 8475 8476 8477 8478 8479 8480 8481 8482 8483 8484 8485 8486 8487 8488 8489 8490 8491 8492 8493 8494 8495 8496 8497 8498 8499 8500 8501 8502 8503 8504 8505 8506 8507 8508 8509 8510 8511 8512 8513 8514 8515 8516 8517 8518 8519 8520 8521 8522 8523 8524 8525 8526 8527 8528 8529 8530 8531 8532 8533 8534 8535 8536 8537 8538 8539 8540 8541 8542 8543 8544 8545 8546 8547 8548 8549 8550 8551 8552 8553 8554 8555 8556 8557 8558 8559 8560 8561 8562 8563 8564 8565 8566 8567 8568 8569 8570 8571 8572 8573 8574 8575 8576 8577 8578 8579 8580 8581 8582 8583 8584 8585 8586 8587 8588 8589 8590 8591 8592 8593 8594 8595 8596 8597 8598 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 8614 8615 8616 8617 8618 8619 8620 8621 8622 8623 8624 8625 8626 8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 8664 8665 8666 8667 8668 8669 8670 8671 8672 8673 8674 8675 8676 8677 8678 8679 8680 8681 8682 8683 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 8699 8700 8701 8702 8703 8704 8705 8706 8707 8708 8709 8710 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 8727 8728 8729 8730 8731 8732 8733 8734 8735 8736 8737 8738 8739 8740 8741 8742 8743 8744 8745 8746 8747 8748 8749 8750 8751 8752 8753 8754 8755 8756 8757 8758 8759 8760 8761 8762 8763 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 8780 8781 8782 8783 8784 8785 8786 8787 8788 8789 8790 8791 8792 8793 8794 8795 8796 8797 8798 8799 8800 8801 8802 8803 8804 8805 8806 8807 8808 8809 8810 8811 8812 8813 8814 8815 8816 8817 8818 8819 8820 8821 8822 8823 8824 8825 8826 8827 8828 8829 8830 8831 8832 8833 8834 8835 8836 8837 8838 8839 8840 8841 8842 8843 8844 8845 8846 8847 8848 8849 8850 8851 8852 8853 8854 8855 8856 8857 8858 8859 8860 8861 8862 8863 8864 8865 8866 8867 8868 8869 8870 8871 8872 8873 8874 8875 8876 8877 8878 8879 8880 8881 8882 8883 8884 8885 8886 8887 8888 8889 8890 8891 8892 8893 8894 8895 8896 8897 8898 8899 8900 8901 8902 8903 8904 8905 8906 8907 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 8922 8923 8924 8925 8926 8927 8928 8929 8930 8931 8932 8933 8934 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 8949 8950 8951 8952 8953 8954 8955 8956 8957 8958 8959 8960 8961 8962 8963 8964 8965 8966 8967 8968 8969 8970 8971 8972 8973 8974 8975 8976 8977 8978 8979 8980 8981 8982 8983 8984 8985 8986 8987 8988 8989 8990 8991 8992 8993 8994 8995 8996 8997 8998 8999 9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040 9041 9042 9043 9044 9045 9046 9047 9048 9049 9050 9051 9052 9053 9054 9055 9056 9057 9058 9059 9060 9061 9062 9063 9064 9065 9066 9067 9068 9069 9070 9071 9072 9073 9074 9075 9076 9077 9078 9079 9080 9081 9082 9083 9084 9085 9086 9087 9088 9089 9090 9091 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 9136 9137 9138 9139 9140 9141 9142 9143 9144 9145 9146 9147 9148 9149 9150 9151 9152 9153 9154 9155 9156 9157 9158 9159 9160 9161 9162 9163 9164 9165 9166 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 9197 9198 9199 9200 9201 9202 9203 9204 9205 9206 9207 9208 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 9223 9224 9225 9226 9227 9228 9229 9230 9231 9232 9233 9234 9235 9236 9237 9238 9239 9240 9241 9242 9243 9244 9245 9246 9247 9248 9249 9250 9251 9252 9253 9254 9255 9256 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 9272 9273 9274 9275 9276 9277 9278 9279 9280 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 9296 9297 9298 9299 9300 9301 9302 9303 9304 9305 9306 9307 9308 9309 9310 9311 9312 9313 9314 9315 9316 9317 9318 9319 9320 9321 9322 9323 9324 9325 9326 9327 9328 9329 9330 9331 9332 9333 9334 9335 9336 9337 9338 9339 9340 9341 9342 9343 9344 9345 9346 9347 9348 9349 9350 9351 9352 9353 9354 9355 9356 9357 9358 9359 9360 9361 9362 9363 9364 9365 9366 9367 9368 9369 9370 9371 9372 9373 9374 9375 9376 9377 9378 9379 9380 9381 9382 9383 9384 9385 9386 9387 9388 9389 9390 9391 9392 9393 9394 9395 9396 9397 9398 9399 9400 9401 9402 9403 9404 9405 9406 9407 9408 9409 9410 9411 9412 9413 9414 9415 9416 9417 9418 9419 9420 9421 9422 9423 9424 9425 9426 9427 9428 9429 9430 9431 9432 9433 9434 9435 9436 9437 9438 9439 9440 9441 9442 9443 9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 9458 9459 9460 9461 9462 9463 9464 9465 9466 9467 9468 9469 9470 9471 9472 9473 9474 9475 9476 9477 9478 9479 9480 9481 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 9496 9497 9498 9499 9500 9501 9502 9503 9504 9505 9506 9507 9508 9509 9510 9511 9512 9513 9514 9515 9516 9517 9518 9519 9520 9521 9522 9523 9524 9525 9526 9527 9528 9529 9530 9531 9532 9533 9534 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 9587 9588 9589 9590 9591 9592 9593 9594 9595 9596 9597 9598 9599 9600 9601 9602 9603 9604 9605 9606 9607 9608 9609 9610 9611 9612 9613 9614 9615 9616 9617 9618 9619 9620 9621 9622 9623 9624 9625 9626 9627 9628 9629 9630 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 9661 9662 9663 9664 9665 9666 9667 9668 9669 9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 9683 9684 9685 9686 9687 9688 9689 9690 9691 9692 9693 9694 9695 9696 9697 9698 9699 9700 9701 9702 9703 9704 9705 9706 9707 9708 9709 9710 9711 9712 9713 9714 9715 9716 9717 9718 9719 9720 9721 9722 9723 9724 9725 9726 9727 9728 9729 9730 9731 9732 9733 9734 9735 9736 9737 9738 9739 9740 9741 9742 9743 9744 9745 9746 9747 9748 9749 9750 9751 9752 9753 9754 9755 9756 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 9771 9772 9773 9774 9775 9776 9777 9778 9779 9780 9781 9782 9783 9784 9785 9786 9787 9788 9789 9790 9791 9792 9793 9794 9795 9796 9797 9798 9799 9800 9801 9802 9803 9804 9805 9806 9807 9808 9809 9810 9811 9812 9813 9814 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829 9830 9831 9832 9833 9834 9835 9836 9837 9838 9839 9840 9841 9842 9843 9844 9845 9846 9847 9848 9849 9850 9851 9852 9853 9854 9855 9856 9857 9858 9859 9860 9861 9862 9863 9864 9865 9866 9867 9868 9869 9870 9871 9872 9873 9874 9875 9876 9877 9878 9879 9880 9881 9882 9883 9884 9885 9886 9887 9888 9889 9890 9891 9892 9893 9894 9895 9896 9897 9898 9899 9900 9901 9902 9903 9904 9905 9906 9907 9908 9909 9910 9911 9912 9913 9914 9915 9916 9917 9918 9919 9920 9921 9922 9923 9924 9925 9926 9927 9928 9929 9930 9931 9932 9933 9934 9935 9936 9937 9938 9939 9940 9941 9942 9943 9944 9945 9946 9947 9948 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 9972 9973 9974 9975 9976 9977 9978 9979 9980 9981 9982 9983 9984 9985 9986 9987 9988 9989 9990 9991 9992 9993 9994 9995 9996 9997 9998 9999 10000 10001 10002 10003 10004 10005 10006 10007 10008 10009 10010 10011 10012 10013 10014 10015 10016 10017 10018 10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 10039 10040 10041 10042 10043 10044 10045 10046 10047 10048 10049 10050 10051 10052 10053 10054 10055 10056 10057 10058 10059 10060 10061 10062 10063 10064 10065 10066 10067 10068 10069 10070 10071 10072 10073 10074 10075 10076 10077 10078 10079 10080 10081 10082 10083 10084 10085 10086 10087 10088 10089 10090 10091 10092 10093 10094 10095 10096 10097 10098 10099 10100 10101 10102 10103 10104 10105 10106 10107 10108 10109 10110 10111 10112 10113 10114 10115 10116 10117 10118 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132 10133 10134 10135 10136 10137 10138 10139 10140 10141 10142 10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 10153 10154 10155 10156 10157 10158 10159 10160 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173 10174 10175 10176 10177 10178 10179 10180 10181 10182 10183 10184 10185 10186 10187 10188 10189 10190 10191 10192 10193 10194 10195 10196 10197 10198 10199 10200 10201 10202 10203 10204 10205 10206 10207 10208 10209 10210 10211 10212 10213 10214 10215 10216 10217 10218 10219 10220 10221 10222 10223 10224 10225 10226 10227 10228 10229 10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 10245 10246 10247 10248 10249 10250 10251 10252 10253 10254 10255 10256 10257 10258 10259 10260 10261 10262 10263 10264 10265 10266 10267 10268 10269 10270 10271 10272 10273 10274 10275 10276 10277 10278 10279 10280 10281 10282 10283 10284 10285 10286 10287 10288 10289 10290 10291 10292 10293