Added methods getting the curves supported by the runtime openSSL lib
* dtls/openssl.py: - Added class _EllipticCurve() for easy handling of the builtin curves - Added wrapper get_elliptic_curves() - which uses _EllipticCurve() - Added EC_get_builtin_curves(), EC_KEY_new_by_curve_name() and EC_KEY_free() - Added OBJ_nid2sn() for translating numeric ids to names * dtls/util.py: Added _EC_KEY() derived from _Rsrc() with own free/del methodincoming
parent
75a01ed528
commit
f5b88155fd
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2017-03-17 Björn Freise <mcfreis@gmx.net>
|
||||||
|
|
||||||
|
Added methods getting the curves supported by the runtime openSSL lib
|
||||||
|
|
||||||
|
* dtls/openssl.py:
|
||||||
|
- Added class _EllipticCurve() for easy handling of the builtin curves
|
||||||
|
- Added wrapper get_elliptic_curves() - which uses _EllipticCurve()
|
||||||
|
- Added EC_get_builtin_curves(), EC_KEY_new_by_curve_name() and EC_KEY_free()
|
||||||
|
- Added OBJ_nid2sn() for translating numeric ids to names
|
||||||
|
* dtls/util.py: Added _EC_KEY() derived from _Rsrc() with own free/del method
|
||||||
|
|
||||||
2017-03-17 Björn Freise <mcfreis@gmx.net>
|
2017-03-17 Björn Freise <mcfreis@gmx.net>
|
||||||
|
|
||||||
Added methods for setting and getting the curves used during negotiation and encryption
|
Added methods for setting and getting the curves used during negotiation and encryption
|
||||||
|
|
|
@ -40,7 +40,7 @@ from os import path
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from err import openssl_error
|
from err import openssl_error
|
||||||
from err import SSL_ERROR_NONE
|
from err import SSL_ERROR_NONE
|
||||||
from util import _BIO
|
from util import _EC_KEY, _BIO
|
||||||
import ctypes
|
import ctypes
|
||||||
from ctypes import CDLL
|
from ctypes import CDLL
|
||||||
from ctypes import CFUNCTYPE
|
from ctypes import CFUNCTYPE
|
||||||
|
@ -169,6 +169,56 @@ X509_NAME_MAXLEN = 256
|
||||||
GETS_MAXLEN = 2048
|
GETS_MAXLEN = 2048
|
||||||
|
|
||||||
|
|
||||||
|
class _EllipticCurve(object):
|
||||||
|
_curves = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_elliptic_curves(cls):
|
||||||
|
if cls._curves is None:
|
||||||
|
# Load once
|
||||||
|
cls._curves = cls._load_elliptic_curves()
|
||||||
|
return cls._curves
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _load_elliptic_curves(cls):
|
||||||
|
num_curves = EC_get_builtin_curves(None, 0)
|
||||||
|
if num_curves > 0:
|
||||||
|
builtin_curves = create_string_buffer(sizeof(EC_builtin_curve) * num_curves)
|
||||||
|
EC_get_builtin_curves(cast(builtin_curves, POINTER(EC_builtin_curve)), num_curves)
|
||||||
|
return [cls(c.nid, OBJ_nid2sn(c.nid)) for c in cast(builtin_curves, POINTER(EC_builtin_curve))[:num_curves]]
|
||||||
|
return []
|
||||||
|
|
||||||
|
def __init__(self, nid, name):
|
||||||
|
self.nid = nid
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Curve %d %r>" % (self.nid, self.name)
|
||||||
|
|
||||||
|
def to_EC_KEY(self):
|
||||||
|
key = _EC_KEY(EC_KEY_new_by_curve_name(self.nid))
|
||||||
|
return key if bool(key.value) else None
|
||||||
|
|
||||||
|
|
||||||
|
def get_elliptic_curves():
|
||||||
|
u''' Return the available curves. If not yet loaded, then load them once.
|
||||||
|
|
||||||
|
:rtype: list
|
||||||
|
'''
|
||||||
|
return _EllipticCurve._get_elliptic_curves()
|
||||||
|
|
||||||
|
|
||||||
|
def get_elliptic_curve(name):
|
||||||
|
u''' Return the curve from the given name.
|
||||||
|
|
||||||
|
:rtype: _EllipticCurve
|
||||||
|
'''
|
||||||
|
for curve in get_elliptic_curves():
|
||||||
|
if curve.name == name:
|
||||||
|
return curve
|
||||||
|
raise ValueError("unknown curve name", name)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Parameter data types
|
# Parameter data types
|
||||||
#
|
#
|
||||||
|
@ -226,6 +276,11 @@ class BIO(FuncParam):
|
||||||
super(BIO, self).__init__(value)
|
super(BIO, self).__init__(value)
|
||||||
|
|
||||||
|
|
||||||
|
class EC_KEY(FuncParam):
|
||||||
|
def __init__(self, value):
|
||||||
|
super(EC_KEY, self).__init__(value)
|
||||||
|
|
||||||
|
|
||||||
class X509(FuncParam):
|
class X509(FuncParam):
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
super(X509, self).__init__(value)
|
super(X509, self).__init__(value)
|
||||||
|
@ -331,6 +386,11 @@ class TIMEVAL(Structure):
|
||||||
("tv_usec", c_long)]
|
("tv_usec", c_long)]
|
||||||
|
|
||||||
|
|
||||||
|
class EC_builtin_curve(Structure):
|
||||||
|
_fields_ = [("nid", c_int),
|
||||||
|
("comment", c_char_p)]
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Socket address conversions
|
# Socket address conversions
|
||||||
#
|
#
|
||||||
|
@ -570,11 +630,13 @@ __all__ = [
|
||||||
"SSL_state_string_long", "SSL_alert_type_string_long", "SSL_alert_desc_string_long",
|
"SSL_state_string_long", "SSL_alert_type_string_long", "SSL_alert_desc_string_long",
|
||||||
"SSL_CTX_set_cookie_cb",
|
"SSL_CTX_set_cookie_cb",
|
||||||
"OBJ_obj2txt", "decode_ASN1_STRING", "ASN1_TIME_print",
|
"OBJ_obj2txt", "decode_ASN1_STRING", "ASN1_TIME_print",
|
||||||
|
"OBJ_nid2sn",
|
||||||
"X509_get_notAfter",
|
"X509_get_notAfter",
|
||||||
"ASN1_item_d2i", "GENERAL_NAME_print",
|
"ASN1_item_d2i", "GENERAL_NAME_print",
|
||||||
"sk_value",
|
"sk_value",
|
||||||
"sk_pop_free",
|
"sk_pop_free",
|
||||||
"i2d_X509",
|
"i2d_X509",
|
||||||
|
"get_elliptic_curves",
|
||||||
] # note: the following map adds to this list
|
] # note: the following map adds to this list
|
||||||
|
|
||||||
map(lambda x: _make_function(*x), (
|
map(lambda x: _make_function(*x), (
|
||||||
|
@ -690,6 +752,8 @@ map(lambda x: _make_function(*x), (
|
||||||
((X509, "ret"), (BIO, "bp"), (c_void_p, "x", 1, None), (c_void_p, "cb", 1, None), (c_void_p, "u", 1, None))),
|
((X509, "ret"), (BIO, "bp"), (c_void_p, "x", 1, None), (c_void_p, "cb", 1, None), (c_void_p, "u", 1, None))),
|
||||||
("OBJ_obj2txt", libcrypto,
|
("OBJ_obj2txt", libcrypto,
|
||||||
((c_int, "ret"), (POINTER(c_char), "buf"), (c_int, "buf_len"), (ASN1_OBJECT, "a"), (c_int, "no_name")), False),
|
((c_int, "ret"), (POINTER(c_char), "buf"), (c_int, "buf_len"), (ASN1_OBJECT, "a"), (c_int, "no_name")), False),
|
||||||
|
("OBJ_nid2sn", libcrypto,
|
||||||
|
((c_char_p, "ret"), (c_int, "n")), False),
|
||||||
("CRYPTO_free", libcrypto,
|
("CRYPTO_free", libcrypto,
|
||||||
((None, "ret"), (c_void_p, "ptr"))),
|
((None, "ret"), (c_void_p, "ptr"))),
|
||||||
("ASN1_STRING_to_UTF8", libcrypto,
|
("ASN1_STRING_to_UTF8", libcrypto,
|
||||||
|
@ -733,6 +797,12 @@ map(lambda x: _make_function(*x), (
|
||||||
((c_char_p, "ret"), (SSL_CIPHER, "cipher"))),
|
((c_char_p, "ret"), (SSL_CIPHER, "cipher"))),
|
||||||
("SSL_CIPHER_get_bits", libssl,
|
("SSL_CIPHER_get_bits", libssl,
|
||||||
((c_int, "ret"), (SSL_CIPHER, "cipher"), (POINTER(c_int), "alg_bits", 1, None)), True, None),
|
((c_int, "ret"), (SSL_CIPHER, "cipher"), (POINTER(c_int), "alg_bits", 1, None)), True, None),
|
||||||
|
("EC_get_builtin_curves", libcrypto,
|
||||||
|
((c_int, "ret"), (POINTER(EC_builtin_curve), "r"), (c_int, "nitems"))),
|
||||||
|
("EC_KEY_new_by_curve_name", libcrypto,
|
||||||
|
((EC_KEY, "ret"), (c_int, "nid"))),
|
||||||
|
("EC_KEY_free", libcrypto,
|
||||||
|
((None, "ret"), (EC_KEY, "key"))),
|
||||||
))
|
))
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -821,9 +891,10 @@ def SSL_CTX_build_cert_chain(ctx, flags):
|
||||||
def SSL_CTX_set_ecdh_auto(ctx, onoff):
|
def SSL_CTX_set_ecdh_auto(ctx, onoff):
|
||||||
return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, None)
|
return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, None)
|
||||||
|
|
||||||
def SSL_CTX_set_tmp_ecdh(ctx, ecdh):
|
def SSL_CTX_set_tmp_ecdh(ctx, ec_key):
|
||||||
# return 1 on success and 0 on failure
|
# return 1 on success and 0 on failure
|
||||||
return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH, 0, ecdh)
|
_ec_key_p = cast(ec_key.raw, c_void_p)
|
||||||
|
return _SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH, 0, _ec_key_p)
|
||||||
|
|
||||||
_rint_voidp_ubytep_uintp = CFUNCTYPE(c_int, c_void_p, POINTER(c_ubyte),
|
_rint_voidp_ubytep_uintp = CFUNCTYPE(c_int, c_void_p, POINTER(c_ubyte),
|
||||||
POINTER(c_uint))
|
POINTER(c_uint))
|
||||||
|
@ -1003,6 +1074,10 @@ def OBJ_obj2txt(asn1_object, no_name):
|
||||||
res_len = _OBJ_obj2txt(buf, sizeof(buf), asn1_object, 1 if no_name else 0)
|
res_len = _OBJ_obj2txt(buf, sizeof(buf), asn1_object, 1 if no_name else 0)
|
||||||
return buf.raw[:res_len]
|
return buf.raw[:res_len]
|
||||||
|
|
||||||
|
def OBJ_nid2sn(nid):
|
||||||
|
_name = _OBJ_nid2sn(nid)
|
||||||
|
return cast(_name, c_char_p).value.decode("ascii")
|
||||||
|
|
||||||
def decode_ASN1_STRING(asn1_string):
|
def decode_ASN1_STRING(asn1_string):
|
||||||
utf8_buf_ptr = POINTER(c_ubyte)()
|
utf8_buf_ptr = POINTER(c_ubyte)()
|
||||||
res_len = _ASN1_STRING_to_UTF8(byref(utf8_buf_ptr), asn1_string)
|
res_len = _ASN1_STRING_to_UTF8(byref(utf8_buf_ptr), asn1_string)
|
||||||
|
|
12
dtls/util.py
12
dtls/util.py
|
@ -57,3 +57,15 @@ class _BIO(_Rsrc):
|
||||||
BIO_free(self._value)
|
BIO_free(self._value)
|
||||||
self.owned = False
|
self.owned = False
|
||||||
self._value = None
|
self._value = None
|
||||||
|
|
||||||
|
|
||||||
|
class _EC_KEY(_Rsrc):
|
||||||
|
"""EC KEY wrapper"""
|
||||||
|
def __init__(self, value):
|
||||||
|
super(_EC_KEY, self).__init__(value)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
_logger.debug("Freeing EC_KEY: %d", self.raw)
|
||||||
|
from openssl import EC_KEY_free
|
||||||
|
EC_KEY_free(self._value)
|
||||||
|
self._value = None
|
||||||
|
|
Loading…
Reference in New Issue