diff options
Diffstat (limited to 'src/SWIG/_rsa.i')
-rw-r--r-- | src/SWIG/_rsa.i | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/src/SWIG/_rsa.i b/src/SWIG/_rsa.i new file mode 100644 index 0000000..4ffae01 --- /dev/null +++ b/src/SWIG/_rsa.i @@ -0,0 +1,518 @@ +/* Copyright (c) 1999-2000 Ng Pheng Siong. All rights reserved. */ +/* $Id$ */ + +%{ +#include <openssl/bn.h> +#include <openssl/err.h> +#include <openssl/pem.h> +#include <openssl/rsa.h> +#include <openssl/opensslv.h> +%} + +%apply Pointer NONNULL { RSA * }; +%apply Pointer NONNULL { PyObject *pyfunc }; + +%rename(rsa_size) RSA_size; +extern int RSA_size(const RSA*); +%rename(rsa_new) RSA_new; +extern RSA *RSA_new(void); +%rename(rsa_free) RSA_free; +extern void RSA_free(RSA *); +%rename(rsa_check_key) RSA_check_key; +extern int RSA_check_key(const RSA *); + +%constant int no_padding = RSA_NO_PADDING; +%constant int pkcs1_padding = RSA_PKCS1_PADDING; +%constant int sslv23_padding = RSA_SSLV23_PADDING; +%constant int pkcs1_oaep_padding = RSA_PKCS1_OAEP_PADDING; + +%constant int NID_sha1 = NID_sha1; + +#if OPENSSL_VERSION_NUMBER >= 0x0090800fL +%constant int NID_sha224 = NID_sha224; +%constant int NID_sha256 = NID_sha256; +%constant int NID_sha384 = NID_sha384; +%constant int NID_sha512 = NID_sha512; +#endif + +%constant int NID_md5 = NID_md5; + +%constant int NID_ripemd160 = NID_ripemd160; + +%warnfilter(454) _rsa_err; +%inline %{ +static PyObject *_rsa_err; + +void rsa_init(PyObject *rsa_err) { + Py_INCREF(rsa_err); + _rsa_err = rsa_err; +} +%} + +%inline %{ +RSA *rsa_read_key(BIO *f, PyObject *pyfunc) { + RSA *rsa; + + Py_INCREF(pyfunc); + Py_BEGIN_ALLOW_THREADS + rsa = PEM_read_bio_RSAPrivateKey(f, NULL, passphrase_callback, (void *)pyfunc); + Py_END_ALLOW_THREADS + Py_DECREF(pyfunc); + return rsa; +} +%} + +%inline %{ +int rsa_write_key(RSA *rsa, BIO *f, EVP_CIPHER *cipher, PyObject *pyfunc) { + int ret; + + Py_INCREF(pyfunc); + Py_BEGIN_ALLOW_THREADS + ret = PEM_write_bio_RSAPrivateKey(f, rsa, cipher, NULL, 0, + passphrase_callback, (void *)pyfunc); + Py_END_ALLOW_THREADS + Py_DECREF(pyfunc); + return ret; +} +%} + +%inline %{ +int rsa_write_key_no_cipher(RSA *rsa, BIO *f, PyObject *pyfunc) { + int ret; + + Py_INCREF(pyfunc); + Py_BEGIN_ALLOW_THREADS + ret = PEM_write_bio_RSAPrivateKey(f, rsa, NULL, NULL, 0, + passphrase_callback, (void *)pyfunc); + Py_END_ALLOW_THREADS + Py_DECREF(pyfunc); + return ret; +} +%} + +%threadallow rsa_read_pub_key; +%inline %{ +RSA *rsa_read_pub_key(BIO *f) { + return PEM_read_bio_RSA_PUBKEY(f, NULL, NULL, NULL); +} +%} + +%threadallow rsa_write_pub_key; +%inline %{ +int rsa_write_pub_key(RSA *rsa, BIO *f) { + return PEM_write_bio_RSA_PUBKEY(f, rsa); +} + +PyObject *rsa_get_e(RSA *rsa) { + const BIGNUM* e = NULL; + RSA_get0_key(rsa, NULL, &e, NULL); + if (!e) { + PyErr_SetString(_rsa_err, "'e' is unset"); + return NULL; + } + return bn_to_mpi(e); +} + +PyObject *rsa_get_n(RSA *rsa) { + const BIGNUM* n = NULL; + RSA_get0_key(rsa, &n, NULL, NULL); + if (!n) { + PyErr_SetString(_rsa_err, "'n' is unset"); + return NULL; + } + return bn_to_mpi(n); +} + +PyObject *rsa_set_e(RSA *rsa, PyObject *eval) { + const BIGNUM* n_read = NULL; + BIGNUM* n = NULL; + BIGNUM* e; + + if (!(e = m2_PyObject_AsBIGNUM(eval, _rsa_err))) { + return NULL; + } + + /* n and e must be set at the same time so if e is unset, set it to zero */ + RSA_get0_key(rsa, &n_read, NULL, NULL); + if (!n_read) { + n = BN_new(); + } + + if (RSA_set0_key(rsa, n, e, NULL) != 1) { + PyErr_SetString(_rsa_err, "Cannot set fields of RSA object."); + BN_free(e); + BN_free(n); + return NULL; + } + Py_RETURN_NONE; +} + +PyObject *rsa_set_n(RSA *rsa, PyObject *nval) { + BIGNUM* n; + const BIGNUM* e_read = NULL; + BIGNUM* e = NULL; + + if (!(n = m2_PyObject_AsBIGNUM(nval, _rsa_err))) { + return NULL; + } + + /* n and e must be set at the same time so if e is unset, set it to zero */ + RSA_get0_key(rsa, NULL, &e_read, NULL); + if (!e_read) { + e = BN_new(); + } + + if (RSA_set0_key(rsa, n, e, NULL) != 1) { + PyErr_SetString(_rsa_err, "Cannot set fields of RSA object."); + BN_free(n); + BN_free(e); + return NULL; + } + Py_RETURN_NONE; +} + +PyObject *rsa_set_en(RSA *rsa, PyObject *eval, PyObject* nval) { + BIGNUM* e, *n; + + if (!(e = m2_PyObject_AsBIGNUM(eval, _rsa_err)) || + !(n = m2_PyObject_AsBIGNUM(nval, _rsa_err))) { + return NULL; + } + + if (!RSA_set0_key(rsa, n, e, NULL)) { + PyErr_SetString(_rsa_err, "Cannot set fields of RSA object."); + BN_free(e); + BN_free(n); + return NULL; + } + Py_RETURN_NONE; +} + +static BIGNUM* PyObject_Bin_AsBIGNUM(PyObject* value) { + BIGNUM* bn; + const void* vbuf; + int vlen = 0; + + if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1) + return NULL; + + if (!(bn = BN_bin2bn((unsigned char *)vbuf, vlen, NULL))) { + m2_PyErr_Msg(_rsa_err); + return NULL; + } + + return bn; +} + +PyObject *rsa_set_en_bin(RSA *rsa, PyObject *eval, PyObject* nval) { + BIGNUM* e, *n; + + if (!(e = PyObject_Bin_AsBIGNUM(eval)) || + !(n = PyObject_Bin_AsBIGNUM(nval))) { + return NULL; + } + + if (!RSA_set0_key(rsa, e, n, NULL)) { + PyErr_SetString(_rsa_err, "Cannot set fields of RSA object."); + BN_free(e); + BN_free(n); + return NULL; + } + Py_RETURN_NONE; +} + +PyObject *rsa_private_encrypt(RSA *rsa, PyObject *from, int padding) { + const void *fbuf; + void *tbuf; + int flen = 0, tlen; + PyObject *ret; + + if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) + return NULL; + + if (!(tbuf = PyMem_Malloc(RSA_size(rsa)))) { + PyErr_SetString(PyExc_MemoryError, "rsa_private_encrypt"); + return NULL; + } + tlen = RSA_private_encrypt(flen, (unsigned char *)fbuf, + (unsigned char *)tbuf, rsa, padding); + if (tlen == -1) { + m2_PyErr_Msg(_rsa_err); + PyMem_Free(tbuf); + return NULL; + } + + ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen); + + PyMem_Free(tbuf); + return ret; +} + +PyObject *rsa_public_decrypt(RSA *rsa, PyObject *from, int padding) { + const void *fbuf; + void *tbuf; + int flen = 0, tlen = 0; + PyObject *ret; + + if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) + return NULL; + + /* OpenSSL docs are confused here: it says we only need buffer + * 'RSA_size()-11', but it is true only for RSA PKCS#1 type 1 + * padding. For other uses we need to use different sizes. */ + if (!(tbuf = PyMem_Malloc(RSA_size(rsa)))) { + PyErr_SetString(PyExc_MemoryError, "rsa_public_decrypt"); + return NULL; + } + tlen = RSA_public_decrypt(flen, (unsigned char *)fbuf, + (unsigned char *)tbuf, rsa, padding); + if (tlen == -1) { + m2_PyErr_Msg(_rsa_err); + PyMem_Free(tbuf); + return NULL; + } + + ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen); + + PyMem_Free(tbuf); + return ret; +} + +PyObject *rsa_public_encrypt(RSA *rsa, PyObject *from, int padding) { + const void *fbuf; + void *tbuf; + int flen = 0, tlen; + PyObject *ret; + + if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) + return NULL; + + if (!(tbuf = PyMem_Malloc(RSA_size(rsa)))) { + PyErr_SetString(PyExc_MemoryError, "rsa_public_encrypt"); + return NULL; + } + tlen = RSA_public_encrypt(flen, (unsigned char *)fbuf, + (unsigned char *)tbuf, rsa, padding); + if (tlen == -1) { + m2_PyErr_Msg(_rsa_err); + PyMem_Free(tbuf); + return NULL; + } + + ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen); + + PyMem_Free(tbuf); + return ret; +} + +PyObject *rsa_private_decrypt(RSA *rsa, PyObject *from, int padding) { + const void *fbuf; + void *tbuf; + int flen = 0, tlen; + PyObject *ret; + + if (m2_PyObject_AsReadBufferInt(from, &fbuf, &flen) == -1) + return NULL; + + if (!(tbuf = PyMem_Malloc(RSA_size(rsa)))) { + PyErr_SetString(PyExc_MemoryError, "rsa_private_decrypt"); + return NULL; + } + tlen = RSA_private_decrypt(flen, (unsigned char *)fbuf, + (unsigned char *)tbuf, rsa, padding); + if (tlen == -1) { + m2_PyErr_Msg(_rsa_err); + PyMem_Free(tbuf); + return NULL; + } + ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen); + + PyMem_Free(tbuf); + return ret; +} + +#if OPENSSL_VERSION_NUMBER >= 0x0090708fL +PyObject *rsa_padding_add_pkcs1_pss(RSA *rsa, PyObject *digest, EVP_MD *hash, int salt_length) { + const void *dbuf; + unsigned char *tbuf; + int dlen, result, tlen; + PyObject *ret; + + if (m2_PyObject_AsReadBufferInt(digest, &dbuf, &dlen) == -1) + return NULL; + + tlen = RSA_size(rsa); + + if (!(tbuf = OPENSSL_malloc(tlen))) { + PyErr_SetString(PyExc_MemoryError, "rsa_padding_add_pkcs1_pss"); + return NULL; + } + result = RSA_padding_add_PKCS1_PSS( + rsa, + tbuf, + (unsigned char *)dbuf, + hash, + salt_length); + + if (result == -1) { + m2_PyErr_Msg(_rsa_err); + OPENSSL_cleanse(tbuf, tlen); + OPENSSL_free(tbuf); + return NULL; + } + ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen); + OPENSSL_cleanse(tbuf, tlen); + OPENSSL_free(tbuf); + return ret; +} + +int rsa_verify_pkcs1_pss(RSA *rsa, PyObject *digest, PyObject *signature, EVP_MD *hash, int salt_length) { + const void *dbuf; + const void *sbuf; + int dlen, slen, ret; + + if (m2_PyObject_AsReadBufferInt(digest, &dbuf, &dlen) == -1) { + return 0; + } + + if (m2_PyObject_AsReadBufferInt(signature, &sbuf, &slen) == -1) { + return 0; + } + + ret = RSA_verify_PKCS1_PSS( + rsa, + (unsigned char *)dbuf, + hash, + (unsigned char *)sbuf, + salt_length); + + return ret; +} +#endif + +PyObject *rsa_sign(RSA *rsa, PyObject *py_digest_string, int method_type) { + int digest_len = 0; + int buf_len = 0; + int ret = 0; + unsigned int real_buf_len = 0; + char *digest_string = NULL; + unsigned char * sign_buf = NULL; + PyObject *signature; + + ret = m2_PyString_AsStringAndSizeInt(py_digest_string, &digest_string, + &digest_len); + if (ret == -1) { + /* PyString_AsStringAndSize raises the correct exceptions. */ + return NULL; + } + + buf_len = RSA_size(rsa); + sign_buf = (unsigned char *)PyMem_Malloc(buf_len); + ret = RSA_sign(method_type, (const unsigned char *)digest_string, digest_len, + sign_buf, &real_buf_len, rsa); + + if (!ret) { + m2_PyErr_Msg(_rsa_err); + PyMem_Free(sign_buf); + return NULL; + } + + signature = PyBytes_FromStringAndSize((const char*) sign_buf, buf_len); + + PyMem_Free(sign_buf); + return signature; +} + +int rsa_verify(RSA *rsa, PyObject *py_verify_string, PyObject* py_sign_string, int method_type){ + int ret = 0; + char * sign_string = NULL; + char * verify_string = NULL; + int verify_len = 0; + int sign_len = 0; + + ret = m2_PyString_AsStringAndSizeInt(py_verify_string, &verify_string, + &verify_len); + if (ret == -1) { + /* PyString_AsStringAndSize raises the correct exceptions. */ + return 0; + } + ret = m2_PyString_AsStringAndSizeInt(py_sign_string, &sign_string, + &sign_len); + if (ret == -1) { + return 0; + } + + ret = RSA_verify(method_type, (unsigned char *) verify_string, + verify_len, (unsigned char *) sign_string, + sign_len, rsa); + if (!ret) { + m2_PyErr_Msg(_rsa_err); + return 0; + } + return ret; +} + +PyObject *rsa_generate_key(int bits, unsigned long e, PyObject *pyfunc) { + RSA *rsa; + PyObject *self = NULL; /* bug in SWIG_NewPointerObj as of 3.0.5 */ + BN_GENCB *gencb; + BIGNUM *e_big; + int ret; + + if ((e_big=BN_new()) == NULL) { + m2_PyErr_Msg(_rsa_err); + return NULL; + } + + if (BN_set_word(e_big, e) == 0) { + m2_PyErr_Msg(_rsa_err); + BN_free(e_big); + return NULL; + } + + if ((gencb=BN_GENCB_new()) == NULL) { + m2_PyErr_Msg(_rsa_err); + BN_free(e_big); + return NULL; + } + + if ((rsa = RSA_new()) == NULL) { + m2_PyErr_Msg(_rsa_err); + BN_free(e_big); + BN_GENCB_free(gencb); + return NULL; + } + + BN_GENCB_set(gencb, bn_gencb_callback, (void *) pyfunc); + + Py_INCREF(pyfunc); + ret = RSA_generate_key_ex(rsa, bits, e_big, gencb); + BN_free(e_big); + BN_GENCB_free(gencb); + Py_DECREF(pyfunc); + + if (ret) + return SWIG_NewPointerObj((void *)rsa, SWIGTYPE_p_RSA, 0); + + m2_PyErr_Msg(_rsa_err); + RSA_free(rsa); + return NULL; +} + +int rsa_type_check(RSA *rsa) { + return 1; +} + +int rsa_check_pub_key(RSA *rsa) { + const BIGNUM* n, *e; + RSA_get0_key(rsa, &n, &e, NULL); + return n && e; +} +%} + +%threadallow rsa_write_key_der; +%inline %{ +int rsa_write_key_der(RSA *rsa, BIO *bio) { + return i2d_RSAPrivateKey_bio(bio, rsa); +} +%} |