diff options
Diffstat (limited to 'src/SWIG/_lib.i')
-rw-r--r-- | src/SWIG/_lib.i | 777 |
1 files changed, 777 insertions, 0 deletions
diff --git a/src/SWIG/_lib.i b/src/SWIG/_lib.i new file mode 100644 index 0000000..954e99b --- /dev/null +++ b/src/SWIG/_lib.i @@ -0,0 +1,777 @@ +/* Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved. */ +/* $Id$ */ + +%{ +#include <openssl/bn.h> +#include <openssl/dh.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/rsa.h> +#include <openssl/ssl.h> +#include <openssl/x509.h> +#include <openssl/x509_vfy.h> +#include <ceval.h> +%} + +/* OpenSSL 1.1 compatibility shim */ +%include _lib11_compat.i + +/* Python 3 compatibility shim */ +%include _py3k_compat.i + +%{ +/* OpenSSL 1.0.2 copmatbility shim */ +#if OPENSSL_VERSION_NUMBER < 0x10002000L +typedef void (*OPENSSL_sk_freefunc)(void *); +typedef void *(*OPENSSL_sk_copyfunc)(const void *); +typedef struct stack_st OPENSSL_STACK; + +# define MIN_NODES 4 +# define sk_deep_copy OPENSSL_sk_deep_copy + +void OPENSSL_sk_free(OPENSSL_STACK *st) +{ + if (st == NULL) + return; + OPENSSL_free(st->data); + OPENSSL_free(st); +} + +OPENSSL_STACK *OPENSSL_sk_deep_copy(const OPENSSL_STACK *sk, + OPENSSL_sk_copyfunc copy_func, + OPENSSL_sk_freefunc free_func) +{ + OPENSSL_STACK *ret; + int i; + + if (sk->num < 0) + return NULL; + + if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) + return NULL; + + /* direct structure assignment */ + *ret = *sk; + + ret->num_alloc = sk->num > MIN_NODES ? (size_t)sk->num : MIN_NODES; + ret->data = OPENSSL_zalloc(sizeof(*ret->data) * ret->num_alloc); + if (ret->data == NULL) { + OPENSSL_free(ret); + return NULL; + } + + for (i = 0; i < ret->num; ++i) { + if (sk->data[i] == NULL) + continue; + if ((ret->data[i] = copy_func(sk->data[i])) == NULL) { + while (--i >= 0) + if (ret->data[i] != NULL) + free_func((void *)ret->data[i]); + OPENSSL_sk_free(ret); + return NULL; + } + } + return ret; +} +#endif /* OpenSSL 1.0.2 copmatbility shim */ + + +/* Blob interface. Deprecated. */ + +Blob *blob_new(int len, const char *errmsg) { + + Blob *blob; + if (!(blob=(Blob *)PyMem_Malloc(sizeof(Blob)))){ + PyErr_SetString(PyExc_MemoryError, errmsg); + return NULL; + } + if (!(blob->data=(unsigned char *)PyMem_Malloc(len))) { + PyMem_Free(blob); + PyErr_SetString(PyExc_MemoryError, errmsg); + return NULL; + } + blob->len=len; + return blob; +} + +Blob *blob_copy(Blob *from, const char *errmsg) { + Blob *blob=blob_new(from->len, errmsg); + if (!blob) { + PyErr_SetString(PyExc_MemoryError, errmsg); + return NULL; + } + memcpy(blob->data, from->data, from->len); + return blob; +} + +void blob_free(Blob *blob) { + PyMem_Free(blob->data); + PyMem_Free(blob); +} + + +/* Python helpers. */ + +%} +%ignore PyObject_CheckBuffer; +%ignore PyObject_GetBuffer; +%ignore PyBuffer_Release; +%ignore m2_PyObject_AsReadBuffer; +%ignore m2_PyObject_AsReadBufferInt; +%ignore m2_PyObject_GetBufferInt; +%ignore m2_PyBuffer_Release; +%ignore m2_PyString_AsStringAndSizeInt; +%{ + +static int +m2_PyObject_AsReadBuffer(PyObject * obj, const void **buffer, + Py_ssize_t * buffer_len) +{ + int ret = 0; + Py_ssize_t len = 0; + Py_buffer view; + + if (PyObject_CheckBuffer(obj)) { + if (PyObject_GetBuffer(obj, &view, PyBUF_SIMPLE) == 0) { + *buffer = view.buf; + len = view.len; + } + } else { + if ((ret = PyObject_AsReadBuffer(obj, buffer, &len)) != 0) + return ret; + } + if (len > INT_MAX) { + m2_PyBuffer_Release(obj, &view); + PyErr_SetString(PyExc_ValueError, "object too large"); + return -1; + } + *buffer_len = len; + m2_PyBuffer_Release(obj, &view); + return 0; +} + +static int +m2_PyObject_AsReadBufferInt(PyObject * obj, const void **buffer, + int *buffer_len) +{ + int ret = 0; + Py_ssize_t len = 0; + + ret = m2_PyObject_AsReadBuffer(obj, buffer, &len); + *buffer_len = len; + return ret; +} + + + +static int m2_PyObject_GetBufferInt(PyObject *obj, Py_buffer *view, int flags) +{ + int ret; + + if (PyObject_CheckBuffer(obj)) + ret = PyObject_GetBuffer(obj, view, flags); + else { + const void *buf; + + ret = PyObject_AsReadBuffer(obj, &buf, &view->len); + if (ret == 0) + view->buf = (void *)buf; + } + if (ret) + return ret; + if (view->len > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "object too large"); + m2_PyBuffer_Release(obj, view); + return -1; + } + + return 0; +} + +static BIGNUM* +m2_PyObject_AsBIGNUM(PyObject* value, PyObject* _py_exc) +{ + BIGNUM* bn; + const void* vbuf; + int vlen = 0; + + if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) + return NULL; + + if (!(bn = BN_mpi2bn((unsigned char *)vbuf, vlen, NULL))) { + PyErr_SetString(_py_exc, ERR_reason_error_string(ERR_get_error())); + return NULL; + } + + return bn; +} + +static void m2_PyBuffer_Release(PyObject *obj, Py_buffer *view) +{ + if (PyObject_CheckBuffer(obj)) + PyBuffer_Release(view); + /* else do nothing, view->buf comes from PyObject_AsReadBuffer */ +} + +static int +m2_PyString_AsStringAndSizeInt(PyObject *obj, char **s, int *len) +{ + int ret; + Py_ssize_t len2; + + ret = PyBytes_AsStringAndSize(obj, s, &len2); + + if (ret) + return ret; + if (len2 > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "string too large"); + return -1; + } + *len = len2; + return 0; +} + +/* Works as PyFile_Name, but always returns a new object. */ +PyObject *m2_PyFile_Name(PyObject *pyfile) { + PyObject *out = NULL; +#if PY_MAJOR_VERSION >= 3 + out = PyObject_GetAttrString(pyfile, "name"); +#else + out = PyFile_Name(pyfile); + Py_XINCREF(out); +#endif + return out; +} + +/* Yes, __FUNCTION__ is a non-standard symbol, but it is supported by + * both gcc and MSVC. */ +#define m2_PyErr_Msg(type) m2_PyErr_Msg_Caller(type, (const char*) __FUNCTION__) + +static void m2_PyErr_Msg_Caller(PyObject *err_type, const char* caller) { + const char *err_reason; + const char *data; + int flags; + /* This max size of a (longer than ours) OpenSSL error string is hardcoded + * in OpenSSL's crypto/err/err_prn.c:ERR_print_errors_cb() */ + char err_msg[4096]; + unsigned long err_code = ERR_get_error_line_data(NULL, NULL, &data, &flags); + + if (err_code != 0) { + err_reason = ERR_reason_error_string(err_code); + if (data && (flags & ERR_TXT_STRING)) + snprintf(err_msg, sizeof(err_msg), "%s (%s)", err_reason, data); + else + snprintf(err_msg, sizeof(err_msg), "%s", err_reason); + + PyErr_SetString(err_type, err_msg); + } else { + PyErr_Format(err_type, "Unknown error in function %s.", caller); + } +} + + +/* C callbacks invoked by OpenSSL; these in turn call back into +Python. */ + +int ssl_verify_callback(int ok, X509_STORE_CTX *ctx) { + PyObject *argv, *ret; + PyObject *_x509_store_ctx_swigptr=0, *_x509_store_ctx_obj=0, *_x509_store_ctx_inst=0, *_klass=0; + PyObject *_x509=0, *_ssl_ctx=0; + SSL *ssl; + SSL_CTX *ssl_ctx; + X509 *x509; + int errnum, errdepth; + int cret; + int new_style_callback = 0, warning_raised_exception=0; + PyGILState_STATE gilstate; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ + + ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx); + + gilstate = PyGILState_Ensure(); + + if (PyMethod_Check(ssl_verify_cb_func)) { + PyObject *func; + PyCodeObject *code; + func = PyMethod_Function(ssl_verify_cb_func); + code = (PyCodeObject *) PyFunction_GetCode(func); + if (code && code->co_argcount == 3) { /* XXX Python internals */ + new_style_callback = 1; + } + } else if (PyFunction_Check(ssl_verify_cb_func)) { + PyCodeObject *code = (PyCodeObject *) PyFunction_GetCode(ssl_verify_cb_func); + if (code && code->co_argcount == 2) { /* XXX Python internals */ + new_style_callback = 1; + } + } else { + /* XXX There are lots of other callable types, but we will assume + * XXX that any other type of callable uses the new style callback, + * XXX although this is not entirely safe assumption. + */ + new_style_callback = 1; + } + + if (new_style_callback) { + PyObject *x509mod; + + x509mod = PyDict_GetItemString(PyImport_GetModuleDict(), "M2Crypto.X509"); + _klass = PyObject_GetAttrString(x509mod, "X509_Store_Context"); + + _x509_store_ctx_swigptr = SWIG_NewPointerObj((void *)ctx, SWIGTYPE_p_X509_STORE_CTX, 0); + _x509_store_ctx_obj = Py_BuildValue("(Oi)", _x509_store_ctx_swigptr, 0); + + _x509_store_ctx_inst = PyObject_CallObject(_klass, _x509_store_ctx_obj); + + argv = Py_BuildValue("(iO)", ok, _x509_store_ctx_inst); + } else { + if (PyErr_Warn(PyExc_DeprecationWarning, "Old style callback, use cb_func(ok, store) instead")) { + warning_raised_exception = 1; + } + + x509 = X509_STORE_CTX_get_current_cert(ctx); + errnum = X509_STORE_CTX_get_error(ctx); + errdepth = X509_STORE_CTX_get_error_depth(ctx); + + ssl = (SSL *)X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); + ssl_ctx = SSL_get_SSL_CTX(ssl); + + _x509 = SWIG_NewPointerObj((void *)x509, SWIGTYPE_p_X509, 0); + _ssl_ctx = SWIG_NewPointerObj((void *)ssl_ctx, SWIGTYPE_p_SSL_CTX, 0); + argv = Py_BuildValue("(OOiii)", _ssl_ctx, _x509, errnum, errdepth, ok); + } + + if (!warning_raised_exception) { + ret = PyEval_CallObject(ssl_verify_cb_func, argv); + } else { + ret = 0; + } + + if (!ret) { + /* Got an exception in PyEval_CallObject(), let's fail verification + * to be safe. + */ + cret = 0; + } else { + /* FIXME This is possibly problematic if ret > MAXINT */ + cret = (int)PyLong_AsLong(ret); + } + Py_XDECREF(ret); + Py_XDECREF(argv); + if (new_style_callback) { + Py_XDECREF(_x509_store_ctx_inst); + Py_XDECREF(_x509_store_ctx_obj); + Py_XDECREF(_x509_store_ctx_swigptr); + Py_XDECREF(_klass); + } else { + Py_XDECREF(_x509); + Py_XDECREF(_ssl_ctx); + } + + PyGILState_Release(gilstate); + + return cret; +} + +int x509_store_verify_callback(int ok, X509_STORE_CTX *ctx) { + PyGILState_STATE gilstate; + PyObject *argv, *ret; + PyObject *_x509_store_ctx_swigptr=0, *_x509_store_ctx_obj=0, *_x509_store_ctx_inst=0, *_klass=0; + int cret; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ + PyObject *x509mod; + + + gilstate = PyGILState_Ensure(); + + /* Below, handle only what is called 'new style callback' in ssl_verify_callback(). + TODO: does 'old style callback' exist any more? */ + x509mod = PyDict_GetItemString(PyImport_GetModuleDict(), "M2Crypto.X509"); + _klass = PyObject_GetAttrString(x509mod, "X509_Store_Context"); + _x509_store_ctx_swigptr = SWIG_NewPointerObj((void *)ctx, SWIGTYPE_p_X509_STORE_CTX, 0); + _x509_store_ctx_obj = Py_BuildValue("(Oi)", _x509_store_ctx_swigptr, 0); + + _x509_store_ctx_inst = PyObject_CallObject(_klass, _x509_store_ctx_obj); + + argv = Py_BuildValue("(iO)", ok, _x509_store_ctx_inst); + + ret = PyEval_CallObject(x509_store_verify_cb_func, argv); + if (!ret) { + /* Got an exception in PyEval_CallObject(), let's fail verification + * to be safe. + */ + cret = 0; + } else { + cret = (int)PyInt_AsLong(ret); + } + + Py_XDECREF(ret); + Py_XDECREF(argv); + Py_XDECREF(_x509_store_ctx_inst); + Py_XDECREF(_x509_store_ctx_obj); + Py_XDECREF(_x509_store_ctx_swigptr); + Py_XDECREF(_klass); + + PyGILState_Release(gilstate); + return cret; +} + +void ssl_info_callback(const SSL *s, int where, int ret) { + PyObject *argv, *retval, *_SSL; + PyGILState_STATE gilstate; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ + + gilstate = PyGILState_Ensure(); + + _SSL = SWIG_NewPointerObj((void *)s, SWIGTYPE_p_SSL, 0); + argv = Py_BuildValue("(iiO)", where, ret, _SSL); + + retval = PyEval_CallObject(ssl_info_cb_func, argv); + + Py_XDECREF(retval); + Py_XDECREF(argv); + Py_XDECREF(_SSL); + + PyGILState_Release(gilstate); +} + +DH *ssl_set_tmp_dh_callback(SSL *ssl, int is_export, int keylength) { + PyObject *argv, *ret, *_ssl; + DH *dh; + PyGILState_STATE gilstate; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ + + gilstate = PyGILState_Ensure(); + + _ssl = SWIG_NewPointerObj((void *)ssl, SWIGTYPE_p_SSL, 0); + argv = Py_BuildValue("(Oii)", _ssl, is_export, keylength); + + ret = PyEval_CallObject(ssl_set_tmp_dh_cb_func, argv); + + if ((SWIG_ConvertPtr(ret, (void **)&dh, SWIGTYPE_p_DH, SWIG_POINTER_EXCEPTION | 0)) == -1) + dh = NULL; + Py_XDECREF(ret); + Py_XDECREF(argv); + Py_XDECREF(_ssl); + + PyGILState_Release(gilstate); + + return dh; +} + +RSA *ssl_set_tmp_rsa_callback(SSL *ssl, int is_export, int keylength) { + PyObject *argv, *ret, *_ssl; + RSA *rsa; + PyGILState_STATE gilstate; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ + + gilstate = PyGILState_Ensure(); + + _ssl = SWIG_NewPointerObj((void *)ssl, SWIGTYPE_p_SSL, 0); + argv = Py_BuildValue("(Oii)", _ssl, is_export, keylength); + + ret = PyEval_CallObject(ssl_set_tmp_rsa_cb_func, argv); + + if ((SWIG_ConvertPtr(ret, (void **)&rsa, SWIGTYPE_p_RSA, SWIG_POINTER_EXCEPTION | 0)) == -1) + rsa = NULL; + Py_XDECREF(ret); + Py_XDECREF(argv); + Py_XDECREF(_ssl); + + PyGILState_Release(gilstate); + + return rsa; +} + +/* Universal callback for dh_generate_parameters, + * dsa_generate_parametersm, and rsa_generate_key */ +int bn_gencb_callback(int p, int n, BN_GENCB *gencb) { + PyObject *argv, *ret, *cbfunc; + + cbfunc = (PyObject *)BN_GENCB_get_arg(gencb); + argv = Py_BuildValue("(ii)", p, n); + ret = PyEval_CallObject(cbfunc, argv); + PyErr_Clear(); + Py_DECREF(argv); + Py_XDECREF(ret); + return 1; +} + +int passphrase_callback(char *buf, int num, int v, void *arg) { + int i; + Py_ssize_t len; + char *str; + PyObject *argv, *ret, *cbfunc; + PyGILState_STATE gilstate; + + gilstate = PyGILState_Ensure(); + cbfunc = (PyObject *)arg; + argv = Py_BuildValue("(i)", v); + /* PyEval_CallObject sets exception, if needed. */ + ret = PyEval_CallObject(cbfunc, argv); + Py_DECREF(argv); + if (ret == NULL) { + PyGILState_Release(gilstate); + return -1; + } + + if (!PyBytes_Check(ret)) { + PyErr_SetString(PyExc_RuntimeError, + "Result of callback is not bytes()."); + Py_DECREF(ret); + PyGILState_Release(gilstate); + return -1; + } + if ((len = PyBytes_Size(ret)) > num) + len = num; + str = PyBytes_AsString(ret); + + for (i = 0; i < len; i++) + buf[i] = str[i]; + Py_DECREF(ret); + PyGILState_Release(gilstate); + return len; +} +%} + +%inline %{ + +void lib_init() { +#if OPENSSL_VERSION_NUMBER < 0x10100000L + SSLeay_add_all_algorithms(); + ERR_load_ERR_strings(); +#endif +} + +/* Bignum routines that aren't not numerous enough to +warrant a separate file. */ + +PyObject *bn_to_mpi(const BIGNUM *bn) { + int len = 0; + unsigned char *mpi; + PyObject *pyo; + + len = BN_bn2mpi(bn, NULL); + if (!(mpi=(unsigned char *)PyMem_Malloc(len))) { + m2_PyErr_Msg(PyExc_MemoryError); + return NULL; + } + len=BN_bn2mpi(bn, mpi); + + pyo=PyBytes_FromStringAndSize((const char *)mpi, len); + + PyMem_Free(mpi); + return pyo; +} + +const BIGNUM *mpi_to_bn(PyObject *value) { + const void *vbuf; + int vlen = 0; + + if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) + return NULL; + + return BN_mpi2bn(vbuf, vlen, NULL); +} + +PyObject *bn_to_bin(BIGNUM *bn) { + int len = 0; + unsigned char *bin; + PyObject *pyo; + + len = BN_num_bytes(bn); + if (!(bin=(unsigned char *)PyMem_Malloc(len))) { + PyErr_SetString(PyExc_MemoryError, "bn_to_bin"); + return NULL; + } + BN_bn2bin(bn, bin); + + pyo=PyBytes_FromStringAndSize((const char *)bin, len); + + PyMem_Free(bin); + return pyo; +} + +const BIGNUM *bin_to_bn(PyObject *value) { + const void *vbuf; + int vlen = 0; + + if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) + return NULL; + + return BN_bin2bn(vbuf, vlen, NULL); +} + +PyObject *bn_to_hex(BIGNUM *bn) { + char *hex; + PyObject *pyo; + Py_ssize_t len = 0; + + hex = BN_bn2hex(bn); + if (!hex) { + m2_PyErr_Msg(PyExc_RuntimeError); + OPENSSL_free(hex); + return NULL; + } + len = strlen(hex); + + pyo=PyBytes_FromStringAndSize(hex, len); + + OPENSSL_free(hex); + return pyo; +} + +BIGNUM *hex_to_bn(PyObject *value) { + const void *vbuf; + Py_ssize_t vlen = 0; + BIGNUM *bn; + Py_buffer view; + + if (PyObject_CheckBuffer(value)) { + if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) == 0) { + vbuf = view.buf; + vlen = view.len; + } + } + else { + if (PyObject_AsReadBuffer(value, &vbuf, &vlen) == -1) + return NULL; + } + + if ((bn=BN_new())==NULL) { + m2_PyBuffer_Release(value, &view); + PyErr_SetString(PyExc_MemoryError, "hex_to_bn"); + return NULL; + } + if (BN_hex2bn(&bn, (const char *)vbuf) <= 0) { + m2_PyBuffer_Release(value, &view); + m2_PyErr_Msg(PyExc_RuntimeError); + BN_free(bn); + return NULL; + } + m2_PyBuffer_Release(value, &view); + return bn; +} + +BIGNUM *dec_to_bn(PyObject *value) { + const void *vbuf; + Py_ssize_t vlen = 0; + BIGNUM *bn; + Py_buffer view; + + if (PyObject_CheckBuffer(value)) { + if (PyObject_GetBuffer(value, &view, PyBUF_SIMPLE) == 0) { + vbuf = view.buf; + vlen = view.len; + } + } + else { + if (PyObject_AsReadBuffer(value, &vbuf, &vlen) == -1) + return NULL; + } + + if ((bn=BN_new())==NULL) { + m2_PyBuffer_Release(value, &view); + PyErr_SetString(PyExc_MemoryError, "dec_to_bn"); + return NULL; + } + if ((BN_dec2bn(&bn, (const char *)vbuf) <= 0)) { + m2_PyBuffer_Release(value, &view); + m2_PyErr_Msg(PyExc_RuntimeError); + BN_free(bn); + return NULL; + } + m2_PyBuffer_Release(value, &view); + return bn; +} +%} + + +/* Various useful typemaps. */ + +%typemap(in) Blob * { + Py_ssize_t len = 0; + + if (!PyBytes_Check($input)) { + PyErr_SetString(PyExc_TypeError, "expected PyString"); + return NULL; + } + len=PyBytes_Size($input); + + if (len > INT_MAX) { + PyErr_SetString(PyExc_ValueError, "object too large"); + return NULL; + } + $1=(Blob *)PyMem_Malloc(sizeof(Blob)); + if (!$1) { + PyErr_SetString(PyExc_MemoryError, "malloc Blob"); + return NULL; + } + + $1->data=(unsigned char *)PyBytes_AsString($input); + + $1->len=len; +} + +%typemap(out) Blob * { + if ($1==NULL) { + Py_INCREF(Py_None); + $result=Py_None; + } else { + + $result=PyBytes_FromStringAndSize((const char *)$1->data, $1->len); + + PyMem_Free($1->data); + PyMem_Free($1); + } +} + +%typemap(in) PyObject *pyfunc { + if (!PyCallable_Check($input)) { + PyErr_SetString(PyExc_TypeError, "expected PyCallable"); + return NULL; + } + $1=$input; +} + +%typemap(in) PyObject *pyblob { + if (!PyBytes_Check($input)) { + + PyErr_SetString(PyExc_TypeError, "expected PyString"); + return NULL; + } + $1=$input; +} + +%typemap(in) PyObject * { + $1=$input; +} + +%typemap(out) PyObject * { + $result=$1; +} + +%typemap(out) int { + $result=PyLong_FromLong($1); + if (PyErr_Occurred()) SWIG_fail; +} + +/* Pointer checks. */ + +%apply Pointer NONNULL { Blob * }; + + +/* A bunch of "straight-thru" functions. */ + +%rename(err_print_errors) ERR_print_errors; +%threadallow ERR_print_errors; +extern void ERR_print_errors(BIO *); +%rename(err_get_error) ERR_get_error; +extern unsigned long ERR_get_error(void); +%rename(err_peek_error) ERR_peek_error; +extern unsigned long ERR_peek_error(void); +%rename(err_lib_error_string) ERR_lib_error_string; +extern const char *ERR_lib_error_string(unsigned long); +%rename(err_func_error_string) ERR_func_error_string; +extern const char *ERR_func_error_string(unsigned long); +%rename(err_reason_error_string) ERR_reason_error_string; +extern const char *ERR_reason_error_string(unsigned long); |