From fe7f8f6c956c85ff70c533497ac01f122de80ef2 Mon Sep 17 00:00:00 2001
From: Peter Surda <surda@economicsofbitcoin.com>
Date: Sun, 3 Jan 2021 18:23:00 +0100
Subject: [PATCH] OpenSSL improve memory handling

- replace void * with BIGNUM * where applicable
- fixes #1622
- replace 0 with None when using a NULL pointer as parameter
- maybe needs more work in how the data is accessed
- EC_POINT struct is now defined but isn't used yet

Closes: #1707
---
 src/pyelliptic/ecc.py                 |  52 ++++----
 src/pyelliptic/eccblind.py            |  29 ++---
 src/pyelliptic/openssl.py             | 167 +++++++++++++++-----------
 src/pyelliptic/tests/test_blindsig.py |   4 +-
 4 files changed, 140 insertions(+), 112 deletions(-)

diff --git a/src/pyelliptic/ecc.py b/src/pyelliptic/ecc.py
index 388227c7..fb1dd004 100644
--- a/src/pyelliptic/ecc.py
+++ b/src/pyelliptic/ecc.py
@@ -80,10 +80,9 @@ class ECC(object):
             self.pubkey_y = None
             self.privkey = None
             raise Exception("Bad ECC keys ...")
-        else:
-            self.pubkey_x = pubkey_x
-            self.pubkey_y = pubkey_y
-            self.privkey = privkey
+        self.pubkey_x = pubkey_x
+        self.pubkey_y = pubkey_y
+        self.privkey = privkey
 
     @staticmethod
     def get_curves():
@@ -209,8 +208,8 @@ class ECC(object):
             if other_key == 0:
                 raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
 
-            other_pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0)
-            other_pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0)
+            other_pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), None)
+            other_pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), None)
 
             other_group = OpenSSL.EC_KEY_get0_group(other_key)
             other_pub_key = OpenSSL.EC_POINT_new(other_group)
@@ -231,7 +230,7 @@ class ECC(object):
             if own_key == 0:
                 raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
             own_priv_key = OpenSSL.BN_bin2bn(
-                self.privkey, len(self.privkey), 0)
+                self.privkey, len(self.privkey), None)
 
             if (OpenSSL.EC_KEY_set_private_key(own_key, own_priv_key)) == 0:
                 raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ...")
@@ -277,16 +276,14 @@ class ECC(object):
             curve = self.curve
         elif isinstance(curve, str):
             curve = OpenSSL.get_curve(curve)
-        else:
-            curve = curve
         try:
             key = OpenSSL.EC_KEY_new_by_curve_name(curve)
             if key == 0:
                 raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
             if privkey is not None:
-                priv_key = OpenSSL.BN_bin2bn(privkey, len(privkey), 0)
-            pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), 0)
-            pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), 0)
+                priv_key = OpenSSL.BN_bin2bn(privkey, len(privkey), None)
+            pub_key_x = OpenSSL.BN_bin2bn(pubkey_x, len(pubkey_x), None)
+            pub_key_y = OpenSSL.BN_bin2bn(pubkey_y, len(pubkey_y), None)
 
             if privkey is not None:
                 if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0:
@@ -336,9 +333,11 @@ class ECC(object):
             if key == 0:
                 raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
 
-            priv_key = OpenSSL.BN_bin2bn(self.privkey, len(self.privkey), 0)
-            pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0)
-            pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0)
+            priv_key = OpenSSL.BN_bin2bn(self.privkey, len(self.privkey), None)
+            pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x),
+                                          None)
+            pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y),
+                                          None)
 
             if (OpenSSL.EC_KEY_set_private_key(key, priv_key)) == 0:
                 raise Exception("[OpenSSL] EC_KEY_set_private_key FAIL ...")
@@ -403,8 +402,10 @@ class ECC(object):
             if key == 0:
                 raise Exception("[OpenSSL] EC_KEY_new_by_curve_name FAIL ...")
 
-            pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x), 0)
-            pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y), 0)
+            pub_key_x = OpenSSL.BN_bin2bn(self.pubkey_x, len(self.pubkey_x),
+                                          None)
+            pub_key_y = OpenSSL.BN_bin2bn(self.pubkey_y, len(self.pubkey_y),
+                                          None)
             group = OpenSSL.EC_KEY_get0_group(key)
             pub_key = OpenSSL.EC_POINT_new(group)
 
@@ -475,9 +476,9 @@ class ECC(object):
         key = sha512(ephem.raw_get_ecdh_key(pubkey_x, pubkey_y)).digest()
         key_e, key_m = key[:32], key[32:]
         pubkey = ephem.get_pubkey()
-        iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize())
-        ctx = Cipher(key_e, iv, 1, ciphername)
-        ciphertext = iv + pubkey + ctx.ciphering(data)
+        _iv = OpenSSL.rand(OpenSSL.get_cipher(ciphername).get_blocksize())
+        ctx = Cipher(key_e, _iv, 1, ciphername)
+        ciphertext = _iv + pubkey + ctx.ciphering(data)
         mac = hmac_sha256(key_m, ciphertext)
         return ciphertext + mac
 
@@ -486,10 +487,10 @@ class ECC(object):
         Decrypt data with ECIES method using the local private key
         """
         blocksize = OpenSSL.get_cipher(ciphername).get_blocksize()
-        iv = data[:blocksize]
+        _iv = data[:blocksize]
         i = blocksize
-        _, pubkey_x, pubkey_y, i2 = ECC._decode_pubkey(data[i:])
-        i += i2
+        _, pubkey_x, pubkey_y, _i2 = ECC._decode_pubkey(data[i:])
+        i += _i2
         ciphertext = data[i:len(data) - 32]
         i += len(ciphertext)
         mac = data[i:]
@@ -497,5 +498,6 @@ class ECC(object):
         key_e, key_m = key[:32], key[32:]
         if not equals(hmac_sha256(key_m, data[:len(data) - 32]), mac):
             raise RuntimeError("Fail to verify data")
-        ctx = Cipher(key_e, iv, 0, ciphername)
-        return ctx.ciphering(ciphertext)
+        ctx = Cipher(key_e, _iv, 0, ciphername)
+        retval = ctx.ciphering(ciphertext)
+        return retval
diff --git a/src/pyelliptic/eccblind.py b/src/pyelliptic/eccblind.py
index 83bc7632..df987824 100644
--- a/src/pyelliptic/eccblind.py
+++ b/src/pyelliptic/eccblind.py
@@ -109,7 +109,7 @@ class ECCBlind(object):  # pylint: disable=too-many-instance-attributes
         """
         ECC inversion
         """
-        inverse = OpenSSL.BN_mod_inverse(0, a, self.n, self.ctx)
+        inverse = OpenSSL.BN_mod_inverse(None, a, self.n, self.ctx)
         return inverse
 
     def ec_gen_keypair(self):
@@ -119,7 +119,7 @@ class ECCBlind(object):  # pylint: disable=too-many-instance-attributes
         """
         d = self.ec_get_random()
         Q = OpenSSL.EC_POINT_new(self.group)
-        OpenSSL.EC_POINT_mul(self.group, Q, d, 0, 0, 0)
+        OpenSSL.EC_POINT_mul(self.group, Q, d, None, None, None)
         return (d, Q)
 
     def ec_Ftor(self, F):
@@ -139,7 +139,7 @@ class ECCBlind(object):  # pylint: disable=too-many-instance-attributes
             x = OpenSSL.BN_new()
             y = OpenSSL.BN_new()
             OpenSSL.EC_POINT_get_affine_coordinates(
-                self.group, point, x, y, 0)
+                self.group, point, x, y, None)
             y_byte = (OpenSSL.BN_is_odd(y) & Y_BIT) | COMPRESSED_BIT
             l_ = OpenSSL.BN_num_bytes(self.n)
             try:
@@ -160,7 +160,7 @@ class ECCBlind(object):  # pylint: disable=too-many-instance-attributes
     def _ec_point_deserialize(self, data):
         """Make a string into an EC point"""
         y_bit, x_raw = unpack(EC, data)
-        x = OpenSSL.BN_bin2bn(x_raw, OpenSSL.BN_num_bytes(self.n), 0)
+        x = OpenSSL.BN_bin2bn(x_raw, OpenSSL.BN_num_bytes(self.n), None)
         y_bit &= Y_BIT
         retval = OpenSSL.EC_POINT_new(self.group)
         OpenSSL.EC_POINT_set_compressed_coordinates(self.group,
@@ -184,7 +184,7 @@ class ECCBlind(object):  # pylint: disable=too-many-instance-attributes
 
     def _bn_deserialize(self, data):
         """Make a BigNum out of string"""
-        x = OpenSSL.BN_bin2bn(data, OpenSSL.BN_num_bytes(self.n), 0)
+        x = OpenSSL.BN_bin2bn(data, OpenSSL.BN_num_bytes(self.n), None)
         return x
 
     def _init_privkey(self, privkey):
@@ -261,7 +261,7 @@ class ECCBlind(object):  # pylint: disable=too-many-instance-attributes
 
         # R = kG
         self.R = OpenSSL.EC_POINT_new(self.group)
-        OpenSSL.EC_POINT_mul(self.group, self.R, self.k, 0, 0, 0)
+        OpenSSL.EC_POINT_mul(self.group, self.R, self.k, None, None, None)
 
         return self._ec_point_serialize(self.R)
 
@@ -286,17 +286,18 @@ class ECCBlind(object):  # pylint: disable=too-many-instance-attributes
 
             # F = b^-1 * R...
             self.binv = self.ec_invert(self.b)
-            OpenSSL.EC_POINT_mul(self.group, temp, 0, self.R, self.binv, 0)
+            OpenSSL.EC_POINT_mul(self.group, temp, None, self.R, self.binv,
+                                 None)
             OpenSSL.EC_POINT_copy(self.F, temp)
 
             # ... + a*b^-1 * Q...
             OpenSSL.BN_mul(abinv, self.a, self.binv, self.ctx)
-            OpenSSL.EC_POINT_mul(self.group, temp, 0, self.Q, abinv, 0)
-            OpenSSL.EC_POINT_add(self.group, self.F, self.F, temp, 0)
+            OpenSSL.EC_POINT_mul(self.group, temp, None, self.Q, abinv, None)
+            OpenSSL.EC_POINT_add(self.group, self.F, self.F, temp, None)
 
             # ... + c*G
-            OpenSSL.EC_POINT_mul(self.group, temp, 0, self.G, self.c, 0)
-            OpenSSL.EC_POINT_add(self.group, self.F, self.F, temp, 0)
+            OpenSSL.EC_POINT_mul(self.group, temp, None, self.G, self.c, None)
+            OpenSSL.EC_POINT_add(self.group, self.F, self.F, temp, None)
 
         # F = (x0, y0)
         self.r = self.ec_Ftor(self.F)
@@ -355,10 +356,10 @@ class ECCBlind(object):  # pylint: disable=too-many-instance-attributes
         lhs = OpenSSL.EC_POINT_new(self.group)
         rhs = OpenSSL.EC_POINT_new(self.group)
 
-        OpenSSL.EC_POINT_mul(self.group, lhs, s, 0, 0, 0)
+        OpenSSL.EC_POINT_mul(self.group, lhs, s, None, None, None)
 
-        OpenSSL.EC_POINT_mul(self.group, rhs, 0, self.Q, self.m, 0)
-        OpenSSL.EC_POINT_mul(self.group, rhs, 0, rhs, self.r, 0)
+        OpenSSL.EC_POINT_mul(self.group, rhs, None, self.Q, self.m, None)
+        OpenSSL.EC_POINT_mul(self.group, rhs, None, rhs, self.r, None)
         OpenSSL.EC_POINT_add(self.group, rhs, rhs, self.F, self.ctx)
 
         retval = OpenSSL.EC_POINT_cmp(self.group, lhs, rhs, self.ctx)
diff --git a/src/pyelliptic/openssl.py b/src/pyelliptic/openssl.py
index abc6ac13..ad14ca8a 100644
--- a/src/pyelliptic/openssl.py
+++ b/src/pyelliptic/openssl.py
@@ -72,6 +72,29 @@ def get_version(library):
     return (version, hexversion, cflags)
 
 
+class BIGNUM(ctypes.Structure):  # pylint: disable=too-few-public-methods
+    """OpenSSL's BIGNUM struct"""
+    _fields_ = [
+        ('d', ctypes.POINTER(ctypes.c_ulong)),
+        ('top', ctypes.c_int),
+        ('dmax', ctypes.c_int),
+        ('neg', ctypes.c_int),
+        ('flags', ctypes.c_int),
+    ]
+
+
+class EC_POINT(ctypes.Structure):  # pylint: disable=too-few-public-methods
+    """OpenSSL's EC_POINT struct"""
+    _fields_ = [
+        ('meth', ctypes.c_void_p),
+        ('curve_name', ctypes.c_int),
+        ('X', ctypes.POINTER(BIGNUM)),
+        ('Y', ctypes.POINTER(BIGNUM)),
+        ('Z', ctypes.POINTER(BIGNUM)),
+        ('Z_is_one', ctypes.c_int),
+    ]
+
+
 class _OpenSSL(object):
     """
     Wrapper for OpenSSL using ctypes
@@ -91,38 +114,38 @@ class _OpenSSL(object):
         self.create_string_buffer = ctypes.create_string_buffer
 
         self.BN_new = self._lib.BN_new
-        self.BN_new.restype = ctypes.c_void_p
+        self.BN_new.restype = ctypes.POINTER(BIGNUM)
         self.BN_new.argtypes = []
 
         self.BN_free = self._lib.BN_free
         self.BN_free.restype = None
-        self.BN_free.argtypes = [ctypes.c_void_p]
+        self.BN_free.argtypes = [ctypes.POINTER(BIGNUM)]
 
         self.BN_clear_free = self._lib.BN_clear_free
         self.BN_clear_free.restype = None
-        self.BN_clear_free.argtypes = [ctypes.c_void_p]
+        self.BN_clear_free.argtypes = [ctypes.POINTER(BIGNUM)]
 
         self.BN_num_bits = self._lib.BN_num_bits
         self.BN_num_bits.restype = ctypes.c_int
-        self.BN_num_bits.argtypes = [ctypes.c_void_p]
+        self.BN_num_bits.argtypes = [ctypes.POINTER(BIGNUM)]
 
         self.BN_bn2bin = self._lib.BN_bn2bin
         self.BN_bn2bin.restype = ctypes.c_int
-        self.BN_bn2bin.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
+        self.BN_bn2bin.argtypes = [ctypes.POINTER(BIGNUM), ctypes.c_void_p]
 
         try:
             self.BN_bn2binpad = self._lib.BN_bn2binpad
             self.BN_bn2binpad.restype = ctypes.c_int
-            self.BN_bn2binpad.argtypes = [ctypes.c_void_p, ctypes.c_void_p,
+            self.BN_bn2binpad.argtypes = [ctypes.POINTER(BIGNUM), ctypes.c_void_p,
                                           ctypes.c_int]
         except AttributeError:
             # optional, we have a workaround
             pass
 
         self.BN_bin2bn = self._lib.BN_bin2bn
-        self.BN_bin2bn.restype = ctypes.c_void_p
+        self.BN_bin2bn.restype = ctypes.POINTER(BIGNUM)
         self.BN_bin2bn.argtypes = [ctypes.c_void_p, ctypes.c_int,
-                                   ctypes.c_void_p]
+                                   ctypes.POINTER(BIGNUM)]
 
         self.EC_KEY_free = self._lib.EC_KEY_free
         self.EC_KEY_free.restype = None
@@ -141,11 +164,11 @@ class _OpenSSL(object):
         self.EC_KEY_check_key.argtypes = [ctypes.c_void_p]
 
         self.EC_KEY_get0_private_key = self._lib.EC_KEY_get0_private_key
-        self.EC_KEY_get0_private_key.restype = ctypes.c_void_p
+        self.EC_KEY_get0_private_key.restype = ctypes.POINTER(BIGNUM)
         self.EC_KEY_get0_private_key.argtypes = [ctypes.c_void_p]
 
         self.EC_KEY_get0_public_key = self._lib.EC_KEY_get0_public_key
-        self.EC_KEY_get0_public_key.restype = ctypes.c_void_p
+        self.EC_KEY_get0_public_key.restype = ctypes.POINTER(EC_POINT)
         self.EC_KEY_get0_public_key.argtypes = [ctypes.c_void_p]
 
         self.EC_KEY_get0_group = self._lib.EC_KEY_get0_group
@@ -156,9 +179,9 @@ class _OpenSSL(object):
             self._lib.EC_POINT_get_affine_coordinates_GFp
         self.EC_POINT_get_affine_coordinates_GFp.restype = ctypes.c_int
         self.EC_POINT_get_affine_coordinates_GFp.argtypes = [ctypes.c_void_p,
-                                                             ctypes.c_void_p,
-                                                             ctypes.c_void_p,
-                                                             ctypes.c_void_p,
+                                                             ctypes.POINTER(EC_POINT),
+                                                             ctypes.POINTER(BIGNUM),
+                                                             ctypes.POINTER(BIGNUM),
                                                              ctypes.c_void_p]
 
         try:
@@ -170,20 +193,20 @@ class _OpenSSL(object):
                 self._lib.EC_POINT_get_affine_coordinates_GF2m
         self.EC_POINT_get_affine_coordinates.restype = ctypes.c_int
         self.EC_POINT_get_affine_coordinates.argtypes = [ctypes.c_void_p,
-                                                         ctypes.c_void_p,
-                                                         ctypes.c_void_p,
-                                                         ctypes.c_void_p,
+                                                         ctypes.POINTER(EC_POINT),
+                                                         ctypes.POINTER(BIGNUM),
+                                                         ctypes.POINTER(BIGNUM),
                                                          ctypes.c_void_p]
 
         self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key
         self.EC_KEY_set_private_key.restype = ctypes.c_int
         self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p,
-                                                ctypes.c_void_p]
+                                                ctypes.POINTER(BIGNUM)]
 
         self.EC_KEY_set_public_key = self._lib.EC_KEY_set_public_key
         self.EC_KEY_set_public_key.restype = ctypes.c_int
         self.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p,
-                                               ctypes.c_void_p]
+                                               ctypes.POINTER(EC_POINT)]
 
         self.EC_KEY_set_group = self._lib.EC_KEY_set_group
         self.EC_KEY_set_group.restype = ctypes.c_int
@@ -194,9 +217,9 @@ class _OpenSSL(object):
             self._lib.EC_POINT_set_affine_coordinates_GFp
         self.EC_POINT_set_affine_coordinates_GFp.restype = ctypes.c_int
         self.EC_POINT_set_affine_coordinates_GFp.argtypes = [ctypes.c_void_p,
-                                                             ctypes.c_void_p,
-                                                             ctypes.c_void_p,
-                                                             ctypes.c_void_p,
+                                                             ctypes.POINTER(EC_POINT),
+                                                             ctypes.POINTER(BIGNUM),
+                                                             ctypes.POINTER(BIGNUM),
                                                              ctypes.c_void_p]
 
         try:
@@ -208,9 +231,9 @@ class _OpenSSL(object):
                 self._lib.EC_POINT_set_affine_coordinates_GF2m
         self.EC_POINT_set_affine_coordinates.restype = ctypes.c_int
         self.EC_POINT_set_affine_coordinates.argtypes = [ctypes.c_void_p,
-                                                         ctypes.c_void_p,
-                                                         ctypes.c_void_p,
-                                                         ctypes.c_void_p,
+                                                         ctypes.POINTER(EC_POINT),
+                                                         ctypes.POINTER(BIGNUM),
+                                                         ctypes.POINTER(BIGNUM),
                                                          ctypes.c_void_p]
 
         try:
@@ -219,38 +242,39 @@ class _OpenSSL(object):
         except AttributeError:
             # OpenSSL docs say only use this for backwards compatibility
             self.EC_POINT_set_compressed_coordinates = \
-                self._lib.EC_POINT_set_compressed_coordinates_GF2m
+                self._lib.EC_POINT_set_compressed_coordinates_GFp
         self.EC_POINT_set_compressed_coordinates.restype = ctypes.c_int
         self.EC_POINT_set_compressed_coordinates.argtypes = [ctypes.c_void_p,
-                                                             ctypes.c_void_p,
-                                                             ctypes.c_void_p,
+                                                             ctypes.POINTER(EC_POINT),
+                                                             ctypes.POINTER(BIGNUM),
                                                              ctypes.c_int,
                                                              ctypes.c_void_p]
 
         self.EC_POINT_new = self._lib.EC_POINT_new
-        self.EC_POINT_new.restype = ctypes.c_void_p
+        self.EC_POINT_new.restype = ctypes.POINTER(EC_POINT)
         self.EC_POINT_new.argtypes = [ctypes.c_void_p]
 
         self.EC_POINT_free = self._lib.EC_POINT_free
         self.EC_POINT_free.restype = None
-        self.EC_POINT_free.argtypes = [ctypes.c_void_p]
+        self.EC_POINT_free.argtypes = [ctypes.POINTER(EC_POINT)]
 
         self.BN_CTX_free = self._lib.BN_CTX_free
         self.BN_CTX_free.restype = None
         self.BN_CTX_free.argtypes = [ctypes.c_void_p]
 
         self.EC_POINT_mul = self._lib.EC_POINT_mul
-        self.EC_POINT_mul.restype = None
+        self.EC_POINT_mul.restype = ctypes.c_int
         self.EC_POINT_mul.argtypes = [ctypes.c_void_p,
-                                      ctypes.c_void_p,
-                                      ctypes.c_void_p,
-                                      ctypes.c_void_p,
+                                      ctypes.POINTER(EC_POINT),
+                                      ctypes.POINTER(BIGNUM),
+                                      ctypes.POINTER(EC_POINT),
+                                      ctypes.POINTER(BIGNUM),
                                       ctypes.c_void_p]
 
         self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key
         self.EC_KEY_set_private_key.restype = ctypes.c_int
         self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p,
-                                                ctypes.c_void_p]
+                                                ctypes.POINTER(BIGNUM)]
 
         if self._hexversion >= 0x10100000 and not self._libreSSL:
             self.EC_KEY_OpenSSL = self._lib.EC_KEY_OpenSSL
@@ -469,70 +493,71 @@ class _OpenSSL(object):
         self.BN_CTX_new.argtypes = []
 
         self.BN_dup = self._lib.BN_dup
-        self.BN_dup.restype = ctypes.c_void_p
-        self.BN_dup.argtypes = [ctypes.c_void_p]
+        self.BN_dup.restype = ctypes.POINTER(BIGNUM)
+        self.BN_dup.argtypes = [ctypes.POINTER(BIGNUM)]
 
         self.BN_rand = self._lib.BN_rand
         self.BN_rand.restype = ctypes.c_int
-        self.BN_rand.argtypes = [ctypes.c_void_p,
+        self.BN_rand.argtypes = [ctypes.POINTER(BIGNUM),
+                                 ctypes.c_int,
                                  ctypes.c_int,
                                  ctypes.c_int]
 
         self.BN_set_word = self._lib.BN_set_word
         self.BN_set_word.restype = ctypes.c_int
-        self.BN_set_word.argtypes = [ctypes.c_void_p,
+        self.BN_set_word.argtypes = [ctypes.POINTER(BIGNUM),
                                      ctypes.c_ulong]
 
         self.BN_mul = self._lib.BN_mul
         self.BN_mul.restype = ctypes.c_int
-        self.BN_mul.argtypes = [ctypes.c_void_p,
-                                ctypes.c_void_p,
-                                ctypes.c_void_p,
+        self.BN_mul.argtypes = [ctypes.POINTER(BIGNUM),
+                                ctypes.POINTER(BIGNUM),
+                                ctypes.POINTER(BIGNUM),
                                 ctypes.c_void_p]
 
         self.BN_mod_add = self._lib.BN_mod_add
         self.BN_mod_add.restype = ctypes.c_int
-        self.BN_mod_add.argtypes = [ctypes.c_void_p,
-                                    ctypes.c_void_p,
-                                    ctypes.c_void_p,
-                                    ctypes.c_void_p,
+        self.BN_mod_add.argtypes = [ctypes.POINTER(BIGNUM),
+                                    ctypes.POINTER(BIGNUM),
+                                    ctypes.POINTER(BIGNUM),
+                                    ctypes.POINTER(BIGNUM),
                                     ctypes.c_void_p]
 
         self.BN_mod_inverse = self._lib.BN_mod_inverse
-        self.BN_mod_inverse.restype = ctypes.c_void_p
-        self.BN_mod_inverse.argtypes = [ctypes.c_void_p,
-                                        ctypes.c_void_p,
-                                        ctypes.c_void_p,
+        self.BN_mod_inverse.restype = ctypes.POINTER(BIGNUM)
+        self.BN_mod_inverse.argtypes = [ctypes.POINTER(BIGNUM),
+                                        ctypes.POINTER(BIGNUM),
+                                        ctypes.POINTER(BIGNUM),
                                         ctypes.c_void_p]
 
         self.BN_mod_mul = self._lib.BN_mod_mul
         self.BN_mod_mul.restype = ctypes.c_int
-        self.BN_mod_mul.argtypes = [ctypes.c_void_p,
-                                    ctypes.c_void_p,
-                                    ctypes.c_void_p,
-                                    ctypes.c_void_p,
+        self.BN_mod_mul.argtypes = [ctypes.POINTER(BIGNUM),
+                                    ctypes.POINTER(BIGNUM),
+                                    ctypes.POINTER(BIGNUM),
+                                    ctypes.POINTER(BIGNUM),
                                     ctypes.c_void_p]
 
         self.BN_lshift = self._lib.BN_lshift
         self.BN_lshift.restype = ctypes.c_int
-        self.BN_lshift.argtypes = [ctypes.c_void_p,
-                                   ctypes.c_void_p,
+        self.BN_lshift.argtypes = [ctypes.POINTER(BIGNUM),
+                                   ctypes.POINTER(BIGNUM),
                                    ctypes.c_int]
 
         self.BN_sub_word = self._lib.BN_sub_word
         self.BN_sub_word.restype = ctypes.c_int
-        self.BN_sub_word.argtypes = [ctypes.c_void_p,
+        self.BN_sub_word.argtypes = [ctypes.POINTER(BIGNUM),
                                      ctypes.c_ulong]
 
         self.BN_cmp = self._lib.BN_cmp
         self.BN_cmp.restype = ctypes.c_int
-        self.BN_cmp.argtypes = [ctypes.c_void_p,
-                                ctypes.c_void_p]
+        self.BN_cmp.argtypes = [ctypes.POINTER(BIGNUM),
+                                ctypes.POINTER(BIGNUM)]
 
         try:
             self.BN_is_odd = self._lib.BN_is_odd
             self.BN_is_odd.restype = ctypes.c_int
-            self.BN_is_odd.argtypes = [ctypes.c_void_p]
+            self.BN_is_odd.argtypes = [ctypes.POINTER(BIGNUM)]
         except AttributeError:
             # OpenSSL 1.1.0 implements this as a function, but earlier
             # versions as macro, so we need to workaround
@@ -540,7 +565,7 @@ class _OpenSSL(object):
 
         self.BN_bn2dec = self._lib.BN_bn2dec
         self.BN_bn2dec.restype = ctypes.c_char_p
-        self.BN_bn2dec.argtypes = [ctypes.c_void_p]
+        self.BN_bn2dec.argtypes = [ctypes.POINTER(BIGNUM)]
 
         self.EC_GROUP_new_by_curve_name = self._lib.EC_GROUP_new_by_curve_name
         self.EC_GROUP_new_by_curve_name.restype = ctypes.c_void_p
@@ -549,43 +574,43 @@ class _OpenSSL(object):
         self.EC_GROUP_get_order = self._lib.EC_GROUP_get_order
         self.EC_GROUP_get_order.restype = ctypes.c_int
         self.EC_GROUP_get_order.argtypes = [ctypes.c_void_p,
-                                            ctypes.c_void_p,
+                                            ctypes.POINTER(BIGNUM),
                                             ctypes.c_void_p]
 
         self.EC_GROUP_get_cofactor = self._lib.EC_GROUP_get_cofactor
         self.EC_GROUP_get_cofactor.restype = ctypes.c_int
         self.EC_GROUP_get_cofactor.argtypes = [ctypes.c_void_p,
-                                               ctypes.c_void_p,
+                                               ctypes.POINTER(BIGNUM),
                                                ctypes.c_void_p]
 
         self.EC_GROUP_get0_generator = self._lib.EC_GROUP_get0_generator
-        self.EC_GROUP_get0_generator.restype = ctypes.c_void_p
+        self.EC_GROUP_get0_generator.restype = ctypes.POINTER(EC_POINT)
         self.EC_GROUP_get0_generator.argtypes = [ctypes.c_void_p]
 
         self.EC_POINT_copy = self._lib.EC_POINT_copy
         self.EC_POINT_copy.restype = ctypes.c_int
-        self.EC_POINT_copy.argtypes = [ctypes.c_void_p,
-                                       ctypes.c_void_p]
+        self.EC_POINT_copy.argtypes = [ctypes.POINTER(EC_POINT),
+                                       ctypes.POINTER(EC_POINT)]
 
         self.EC_POINT_add = self._lib.EC_POINT_add
         self.EC_POINT_add.restype = ctypes.c_int
         self.EC_POINT_add.argtypes = [ctypes.c_void_p,
-                                      ctypes.c_void_p,
-                                      ctypes.c_void_p,
-                                      ctypes.c_void_p,
+                                      ctypes.POINTER(EC_POINT),
+                                      ctypes.POINTER(EC_POINT),
+                                      ctypes.POINTER(EC_POINT),
                                       ctypes.c_void_p]
 
         self.EC_POINT_cmp = self._lib.EC_POINT_cmp
         self.EC_POINT_cmp.restype = ctypes.c_int
         self.EC_POINT_cmp.argtypes = [ctypes.c_void_p,
-                                      ctypes.c_void_p,
-                                      ctypes.c_void_p,
+                                      ctypes.POINTER(EC_POINT),
+                                      ctypes.POINTER(EC_POINT),
                                       ctypes.c_void_p]
 
         self.EC_POINT_set_to_infinity = self._lib.EC_POINT_set_to_infinity
         self.EC_POINT_set_to_infinity.restype = ctypes.c_int
         self.EC_POINT_set_to_infinity.argtypes = [ctypes.c_void_p,
-                                                  ctypes.c_void_p]
+                                                  ctypes.POINTER(EC_POINT)]
 
         self._set_ciphers()
         self._set_curves()
diff --git a/src/pyelliptic/tests/test_blindsig.py b/src/pyelliptic/tests/test_blindsig.py
index 9ed72081..8c4b2b9d 100644
--- a/src/pyelliptic/tests/test_blindsig.py
+++ b/src/pyelliptic/tests/test_blindsig.py
@@ -58,7 +58,7 @@ class TestBlindSig(unittest.TestCase):
             x = OpenSSL.BN_new()
             y = OpenSSL.BN_new()
             OpenSSL.EC_POINT_get_affine_coordinates(
-                obj.group, obj.Q, x, y, 0)
+                obj.group, obj.Q, x, y, None)
             self.assertEqual(OpenSSL.BN_is_odd(y),
                              OpenSSL.BN_is_odd_compatible(y))
 
@@ -85,7 +85,7 @@ class TestBlindSig(unittest.TestCase):
                 self.assertEqual(OpenSSL.BN_cmp(y0, y1), 0)
                 self.assertEqual(OpenSSL.BN_cmp(x0, x1), 0)
                 self.assertEqual(OpenSSL.EC_POINT_cmp(obj.group, randompoint,
-                                                      secondpoint, 0), 0)
+                                                      secondpoint, None), 0)
             finally:
                 OpenSSL.BN_free(x0)
                 OpenSSL.BN_free(x1)