summaryrefslogtreecommitdiff
path: root/src/SWIG/_ec.i
diff options
context:
space:
mode:
Diffstat (limited to 'src/SWIG/_ec.i')
-rw-r--r--src/SWIG/_ec.i521
1 files changed, 521 insertions, 0 deletions
diff --git a/src/SWIG/_ec.i b/src/SWIG/_ec.i
new file mode 100644
index 0000000..f47d593
--- /dev/null
+++ b/src/SWIG/_ec.i
@@ -0,0 +1,521 @@
+/* Copyright (c) 1999-2000 Ng Pheng Siong. All rights reserved.
+ Portions copyright (c) 2005-2006 Vrije Universiteit Amsterdam. All rights reserved.
+
+ Most code originally from _dsa.i, _rsa.i and _dh.i and adjusted for EC use.
+*/
+
+%include <openssl/opensslconf.h>
+
+#if OPENSSL_VERSION_NUMBER < 0x0090800fL || defined(OPENSSL_NO_EC)
+#undef OPENSSL_NO_EC
+%constant OPENSSL_NO_EC = 1;
+#else
+%constant OPENSSL_NO_EC = 0;
+
+%{
+#include <openssl/bn.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+#include <openssl/ecdsa.h>
+#include <openssl/ecdh.h>
+%}
+
+%apply Pointer NONNULL { EC_KEY * };
+
+%rename(ec_key_new) EC_KEY_new;
+extern EC_KEY *EC_KEY_new(void);
+%rename(ec_key_free) EC_KEY_free;
+extern void EC_KEY_free(EC_KEY *);
+%rename(ec_key_size) ECDSA_size;
+extern int ECDSA_size(const EC_KEY *);
+%rename(ec_key_gen_key) EC_KEY_generate_key;
+extern int EC_KEY_generate_key(EC_KEY *);
+%rename(ec_key_check_key) EC_KEY_check_key;
+extern int EC_KEY_check_key(const EC_KEY *);
+
+/* Curve identifier constants from OpenSSL */
+%constant int NID_secp112r1 = NID_secp112r1;
+%constant int NID_secp112r2 = NID_secp112r2;
+%constant int NID_secp128r1 = NID_secp128r1;
+%constant int NID_secp128r2 = NID_secp128r2;
+%constant int NID_secp160k1 = NID_secp160k1;
+%constant int NID_secp160r1 = NID_secp160r1;
+%constant int NID_secp160r2 = NID_secp160r2;
+%constant int NID_secp192k1 = NID_secp192k1;
+%constant int NID_secp224k1 = NID_secp224k1;
+%constant int NID_secp224r1 = NID_secp224r1;
+%constant int NID_secp256k1 = NID_secp256k1;
+%constant int NID_secp384r1 = NID_secp384r1;
+%constant int NID_secp521r1 = NID_secp521r1;
+%constant int NID_sect113r1 = NID_sect113r1;
+%constant int NID_sect113r2 = NID_sect113r2;
+%constant int NID_sect131r1 = NID_sect131r1;
+%constant int NID_sect131r2 = NID_sect131r2;
+%constant int NID_sect163k1 = NID_sect163k1;
+%constant int NID_sect163r1 = NID_sect163r1;
+%constant int NID_sect163r2 = NID_sect163r2;
+%constant int NID_sect193r1 = NID_sect193r1;
+%constant int NID_sect193r2 = NID_sect193r2;
+%constant int NID_sect233k1 = NID_sect233k1;
+%constant int NID_sect233r1 = NID_sect233r1;
+%constant int NID_sect239k1 = NID_sect239k1;
+%constant int NID_sect283k1 = NID_sect283k1;
+%constant int NID_sect283r1 = NID_sect283r1;
+%constant int NID_sect409k1 = NID_sect409k1;
+%constant int NID_sect409r1 = NID_sect409r1;
+%constant int NID_sect571k1 = NID_sect571k1;
+%constant int NID_sect571r1 = NID_sect571r1;
+
+%constant int NID_X9_62_prime192v1 = NID_X9_62_prime192v1;
+%constant int NID_X9_62_prime192v2 = NID_X9_62_prime192v2;
+%constant int NID_X9_62_prime192v3 = NID_X9_62_prime192v3;
+%constant int NID_X9_62_prime239v1 = NID_X9_62_prime239v1;
+%constant int NID_X9_62_prime239v2 = NID_X9_62_prime239v2;
+%constant int NID_X9_62_prime239v3 = NID_X9_62_prime239v3;
+%constant int NID_X9_62_prime256v1 = NID_X9_62_prime256v1;
+%constant int NID_X9_62_c2pnb163v1 = NID_X9_62_c2pnb163v1;
+%constant int NID_X9_62_c2pnb163v2 = NID_X9_62_c2pnb163v2;
+%constant int NID_X9_62_c2pnb163v3 = NID_X9_62_c2pnb163v3;
+%constant int NID_X9_62_c2pnb176v1 = NID_X9_62_c2pnb176v1;
+%constant int NID_X9_62_c2tnb191v1 = NID_X9_62_c2tnb191v1;
+%constant int NID_X9_62_c2tnb191v2 = NID_X9_62_c2tnb191v2;
+%constant int NID_X9_62_c2tnb191v3 = NID_X9_62_c2tnb191v3;
+%constant int NID_X9_62_c2pnb208w1 = NID_X9_62_c2pnb208w1;
+%constant int NID_X9_62_c2tnb239v1 = NID_X9_62_c2tnb239v1;
+%constant int NID_X9_62_c2tnb239v2 = NID_X9_62_c2tnb239v2;
+%constant int NID_X9_62_c2tnb239v3 = NID_X9_62_c2tnb239v3;
+%constant int NID_X9_62_c2pnb272w1 = NID_X9_62_c2pnb272w1;
+%constant int NID_X9_62_c2pnb304w1 = NID_X9_62_c2pnb304w1;
+%constant int NID_X9_62_c2tnb359v1 = NID_X9_62_c2tnb359v1;
+%constant int NID_X9_62_c2pnb368w1 = NID_X9_62_c2pnb368w1;
+%constant int NID_X9_62_c2tnb431r1 = NID_X9_62_c2tnb431r1;
+
+%constant int NID_wap_wsg_idm_ecid_wtls1 = NID_wap_wsg_idm_ecid_wtls1;
+%constant int NID_wap_wsg_idm_ecid_wtls3 = NID_wap_wsg_idm_ecid_wtls3;
+%constant int NID_wap_wsg_idm_ecid_wtls4 = NID_wap_wsg_idm_ecid_wtls4;
+%constant int NID_wap_wsg_idm_ecid_wtls5 = NID_wap_wsg_idm_ecid_wtls5;
+%constant int NID_wap_wsg_idm_ecid_wtls6 = NID_wap_wsg_idm_ecid_wtls6;
+%constant int NID_wap_wsg_idm_ecid_wtls7 = NID_wap_wsg_idm_ecid_wtls7;
+%constant int NID_wap_wsg_idm_ecid_wtls8 = NID_wap_wsg_idm_ecid_wtls8;
+%constant int NID_wap_wsg_idm_ecid_wtls9 = NID_wap_wsg_idm_ecid_wtls9;
+%constant int NID_wap_wsg_idm_ecid_wtls10 = NID_wap_wsg_idm_ecid_wtls10;
+%constant int NID_wap_wsg_idm_ecid_wtls11 = NID_wap_wsg_idm_ecid_wtls11;
+%constant int NID_wap_wsg_idm_ecid_wtls12 = NID_wap_wsg_idm_ecid_wtls12;
+
+%constant int NID_ipsec3 = NID_ipsec3;
+%constant int NID_ipsec4 = NID_ipsec4;
+
+
+%warnfilter(454) _ec_err;
+%inline %{
+static PyObject *_ec_err;
+
+void ec_init(PyObject *ec_err) {
+ Py_INCREF(ec_err);
+ _ec_err = ec_err;
+}
+
+PyObject *ec_get_builtin_curves(void) {
+ /* size_t EC_get_builtin_curves(EC_builtin_curve *r, size_t
+ * nitems); */
+ EC_builtin_curve *curves;
+ Py_ssize_t ret_curves = 0;
+ size_t num_curves = EC_get_builtin_curves(NULL, 0);
+ PyObject *ret_tuple = NULL;
+ PyObject *ret_dict = NULL;
+ Py_ssize_t i;
+ const char *comment;
+ const char *sname;
+
+ if (!(curves = PyMem_Malloc(num_curves * sizeof(EC_builtin_curve)))) {
+ PyErr_SetString(PyExc_MemoryError, "ec_get_builtin_curves");
+ return NULL;
+ }
+
+ ret_curves = (Py_ssize_t)EC_get_builtin_curves(curves, num_curves);
+
+ if (!(ret_tuple = PyTuple_New(ret_curves))) {
+ PyErr_SetString(PyExc_MemoryError, "ec_get_builtin_curves");
+ return NULL;
+ }
+
+ for (i = 0; i < ret_curves; i++) {
+ if (!(ret_dict = PyDict_New())) {
+ PyErr_SetString(PyExc_MemoryError, "ec_get_builtin_curves");
+ return NULL;
+ }
+
+ comment = curves[i].comment;
+ sname = OBJ_nid2sn(curves[i].nid);
+ if (sname == NULL)
+ sname = "";
+
+ PyDict_SetItemString(ret_dict, "NID",
+ PyLong_FromLong((long)curves[i].nid));
+ PyDict_SetItemString(ret_dict, "sname",
+ PyString_FromString(sname));
+ PyDict_SetItemString(ret_dict, "comment",
+ PyString_FromString(comment));
+
+ PyTuple_SET_ITEM(ret_tuple, i, ret_dict);
+
+ }
+
+ PyMem_Free(curves);
+
+ return ret_tuple;
+}
+
+EC_KEY* ec_key_new_by_curve_name(int nid)
+{
+ EC_KEY *key;
+ EC_GROUP *group;
+ int ret =0;
+ point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED;
+ int asn1_flag = OPENSSL_EC_NAMED_CURVE;
+
+ /* If I simply do "return EC_KEY_new_by_curve_name(nid);"
+ * I get large public keys (222 vs 84 bytes for sect233k1 curve).
+ * I don't know why that is, but 'openssl ecparam -genkey ...' sets
+ * the ASN.1 flag and the point conversion form, and gets the
+ * small pub keys. So let's do that too.
+ */
+ key = EC_KEY_new();
+ if (!key) {
+ PyErr_SetString(PyExc_MemoryError, "ec_key_new_by_curve_name");
+ return NULL;
+ }
+ group = EC_GROUP_new_by_curve_name(nid);
+ if (!group) {
+ m2_PyErr_Msg(_ec_err);
+ EC_KEY_free(key);
+ return NULL;
+ }
+ EC_GROUP_set_asn1_flag(group, asn1_flag);
+ EC_GROUP_set_point_conversion_form(group, form);
+ ret = EC_KEY_set_group(key, group);
+ EC_GROUP_free(group);
+ if (ret == 0)
+ {
+ /* EC_KEY_set_group only returns 0 or 1, and does not set error. */
+ PyErr_SetString(_ec_err, "cannot set key's group");
+ EC_KEY_free(key);
+ return NULL;
+ }
+
+ return key;
+}
+
+PyObject *ec_key_get_public_der(EC_KEY *key) {
+ char *src=NULL;
+ int src_len=0;
+ PyObject *pyo=NULL;
+
+ /* Convert to binary */
+ src_len = i2d_EC_PUBKEY( key, (unsigned char**)&src );
+ if (src_len < 0)
+ {
+ m2_PyErr_Msg(_ec_err);
+ return NULL;
+ }
+ /* Create a PyBuffer containing a copy of the binary,
+ * to simplify memory deallocation
+ */
+ pyo = PyBytes_FromStringAndSize( src, src_len );
+
+ OPENSSL_free(src);
+
+ return pyo;
+}
+
+PyObject *ec_key_get_public_key(EC_KEY *key) {
+ char *src=NULL;
+ int src_len=0;
+ PyObject *pyo=NULL;
+
+ /* Convert to binary */
+ src_len = i2o_ECPublicKey(key, (unsigned char**)&src);
+ if (src_len < 0)
+ {
+ m2_PyErr_Msg(_ec_err);
+ return NULL;
+ }
+
+ pyo = PyBytes_FromStringAndSize( src, src_len );
+
+ OPENSSL_free(src);
+
+ return pyo;
+}
+
+%}
+
+%threadallow ec_key_read_pubkey;
+%inline %{
+EC_KEY *ec_key_read_pubkey(BIO *f) {
+ return PEM_read_bio_EC_PUBKEY(f, NULL, NULL, NULL);
+}
+%}
+
+%threadallow ec_key_write_pubkey;
+%inline %{
+int ec_key_write_pubkey(EC_KEY *key, BIO *f) {
+ return PEM_write_bio_EC_PUBKEY(f, key );
+}
+%}
+
+%inline %{
+EC_KEY *ec_key_read_bio(BIO *f, PyObject *pyfunc) {
+ EC_KEY *ret;
+
+ Py_INCREF(pyfunc);
+ Py_BEGIN_ALLOW_THREADS
+ ret = PEM_read_bio_ECPrivateKey(f, NULL, passphrase_callback, (void *)pyfunc);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(pyfunc);
+ return ret;
+}
+%}
+
+%inline %{
+int ec_key_write_bio(EC_KEY *key, BIO *f, EVP_CIPHER *cipher, PyObject *pyfunc) {
+ int ret;
+
+ Py_INCREF(pyfunc);
+ Py_BEGIN_ALLOW_THREADS
+ ret = PEM_write_bio_ECPrivateKey(f, key, cipher, NULL, 0,
+ passphrase_callback, (void *)pyfunc);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(pyfunc);
+ return ret;
+}
+%}
+
+%inline %{
+int ec_key_write_bio_no_cipher(EC_KEY *key, BIO *f, PyObject *pyfunc) {
+ int ret;
+
+ Py_INCREF(pyfunc);
+ Py_BEGIN_ALLOW_THREADS
+ ret = PEM_write_bio_ECPrivateKey(f, key, NULL, NULL, 0,
+ passphrase_callback, (void *)pyfunc);
+ Py_END_ALLOW_THREADS
+ Py_DECREF(pyfunc);
+ return ret;
+}
+
+
+PyObject *ecdsa_sig_get_r(ECDSA_SIG *ecdsa_sig) {
+ const BIGNUM* pr;
+ ECDSA_SIG_get0(ecdsa_sig, &pr, NULL);
+ return bn_to_mpi(pr);
+}
+
+PyObject *ecdsa_sig_get_s(ECDSA_SIG *ecdsa_sig) {
+ const BIGNUM* ps;
+ ECDSA_SIG_get0(ecdsa_sig, NULL, &ps);
+ return bn_to_mpi(ps);
+}
+
+PyObject *ecdsa_sign(EC_KEY *key, PyObject *value) {
+ const void *vbuf;
+ int vlen = 0;
+ PyObject *tuple;
+ ECDSA_SIG *sig;
+
+ if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1)
+ return NULL;
+
+ if (!(sig = ECDSA_do_sign(vbuf, vlen, key))) {
+ m2_PyErr_Msg(_ec_err);
+ return NULL;
+ }
+ if (!(tuple = PyTuple_New(2))) {
+ ECDSA_SIG_free(sig);
+ PyErr_SetString(PyExc_RuntimeError, "PyTuple_New() fails");
+ return NULL;
+ }
+ PyTuple_SET_ITEM(tuple, 0, ecdsa_sig_get_r(sig));
+ PyTuple_SET_ITEM(tuple, 1, ecdsa_sig_get_s(sig));
+ ECDSA_SIG_free(sig);
+ return tuple;
+}
+
+int ecdsa_verify(EC_KEY *key, PyObject *value, PyObject *r, PyObject *s) {
+ const void *vbuf, *rbuf, *sbuf;
+ int vlen = 0, rlen = 0, slen = 0;
+ ECDSA_SIG *sig;
+ int ret;
+ BIGNUM* pr, *ps;
+
+ if ((m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1)
+ || (m2_PyObject_AsReadBufferInt(r, &rbuf, &rlen) == -1)
+ || (m2_PyObject_AsReadBufferInt(s, &sbuf, &slen) == -1))
+ return -1;
+
+ if (!(pr = BN_mpi2bn((unsigned char *)rbuf, rlen, NULL))) {
+ m2_PyErr_Msg(_ec_err);
+ return -1;
+ }
+ if (!(ps = BN_mpi2bn((unsigned char *)sbuf, slen, NULL))) {
+ m2_PyErr_Msg(_ec_err);
+ BN_free(pr);
+ return -1;
+ }
+
+ if (!(sig = ECDSA_SIG_new())) {
+ m2_PyErr_Msg(_ec_err);
+ BN_free(pr);
+ BN_free(ps);
+ return -1;
+ }
+ if (!ECDSA_SIG_set0(sig, pr, ps)) {
+ PyErr_SetString(_ec_err, "Cannot set r and s fields of ECDSA_SIG.");
+ ECDSA_SIG_free(sig);
+ BN_free(pr);
+ BN_free(ps);
+ return -1;
+ }
+ ret = ECDSA_do_verify(vbuf, vlen, sig, key);
+ ECDSA_SIG_free(sig);
+ if (ret == -1)
+ m2_PyErr_Msg(_ec_err);
+ return ret;
+}
+
+
+PyObject *ecdsa_sign_asn1(EC_KEY *key, PyObject *value) {
+ const void *vbuf;
+ int vlen = 0;
+ void *sigbuf;
+ unsigned int siglen;
+ PyObject *ret;
+
+ if (m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1)
+ return NULL;
+
+ if (!(sigbuf = PyMem_Malloc(ECDSA_size(key)))) {
+ PyErr_SetString(PyExc_MemoryError, "ecdsa_sign_asn1");
+ return NULL;
+ }
+ if (!ECDSA_sign(0, vbuf, vlen, (unsigned char *)sigbuf, &siglen, key)) {
+ m2_PyErr_Msg(_ec_err);
+ PyMem_Free(sigbuf);
+ return NULL;
+ }
+ ret = PyBytes_FromStringAndSize(sigbuf, siglen);
+
+ PyMem_Free(sigbuf);
+ return ret;
+}
+
+
+int ecdsa_verify_asn1(EC_KEY *key, PyObject *value, PyObject *sig) {
+ const void *vbuf;
+ void *sbuf;
+ int vlen = 0, slen = 0, ret;
+
+ if ((m2_PyObject_AsReadBufferInt(value, &vbuf, &vlen) == -1)
+ || (m2_PyObject_AsReadBufferInt(sig, (const void **)&sbuf, &slen)
+ == -1))
+ return -1;
+
+ if ((ret = ECDSA_verify(0, vbuf, vlen, sbuf, slen, key)) == -1)
+ m2_PyErr_Msg(_ec_err);
+ return ret;
+}
+
+PyObject *ecdh_compute_key(EC_KEY *keypairA, EC_KEY *pubkeyB) {
+ int sharedkeylen;
+ void *sharedkey;
+ const EC_POINT *pkpointB;
+ PyObject *ret;
+ const EC_GROUP* groupA;
+
+ if ((pkpointB = EC_KEY_get0_public_key(pubkeyB)) == NULL)
+ {
+ PyErr_SetString(_ec_err, "Cannot get the public key of EC_KEY object.");
+ return NULL;
+ }
+
+ groupA = EC_KEY_get0_group(keypairA);
+ sharedkeylen = (EC_GROUP_get_degree(groupA) + 7)/8;
+
+ if (!(sharedkey = PyMem_Malloc(sharedkeylen))) {
+ PyErr_SetString(PyExc_MemoryError, "ecdh_compute_key");
+ return NULL;
+ }
+ if ((sharedkeylen = ECDH_compute_key((unsigned char *)sharedkey, sharedkeylen, pkpointB, keypairA, NULL)) == -1) {
+ m2_PyErr_Msg(_ec_err);
+ PyMem_Free(sharedkey);
+ return NULL;
+ }
+
+ ret = PyBytes_FromStringAndSize((const char *)sharedkey, sharedkeylen);
+
+ PyMem_Free(sharedkey);
+
+ return ret;
+}
+
+
+EC_KEY* ec_key_from_pubkey_der(PyObject *pubkey) {
+ const void *keypairbuf;
+ Py_ssize_t keypairbuflen;
+ const unsigned char *tempBuf;
+ EC_KEY *keypair;
+
+ if (PyObject_AsReadBuffer(pubkey, &keypairbuf, &keypairbuflen) == -1)
+ {
+ return NULL;
+ }
+
+ tempBuf = (const unsigned char *)keypairbuf;
+ if ((keypair = d2i_EC_PUBKEY( NULL, &tempBuf, keypairbuflen)) == 0)
+ {
+ m2_PyErr_Msg(_ec_err);
+ return NULL;
+ }
+ return keypair;
+}
+
+EC_KEY* ec_key_from_pubkey_params(int nid, PyObject *pubkey) {
+ const void *keypairbuf;
+ Py_ssize_t keypairbuflen;
+ const unsigned char *tempBuf;
+ EC_KEY *keypair;
+
+ if (PyObject_AsReadBuffer(pubkey, &keypairbuf, &keypairbuflen) == -1)
+ {
+ return NULL;
+ }
+
+ keypair = ec_key_new_by_curve_name(nid);
+ if (!keypair) {
+ m2_PyErr_Msg(_ec_err);
+ return NULL;
+ }
+
+ tempBuf = (const unsigned char *)keypairbuf;
+ if ((o2i_ECPublicKey( &keypair, &tempBuf, keypairbuflen)) == 0)
+ {
+ m2_PyErr_Msg(_ec_err);
+ return NULL;
+ }
+ return keypair;
+}
+
+
+// According to [SEC2] the degree of the group is defined as EC key length
+int ec_key_keylen(EC_KEY *key) {
+ const EC_GROUP *group = EC_KEY_get0_group(key);
+ return EC_GROUP_get_degree(group);
+}
+
+int ec_key_type_check(EC_KEY *key) {
+ return 1;
+}
+%}
+#endif // if OpenSSL version with EC support
+