Adding DTLS support

pull/35/head
Lealem Amedie 2022-08-18 15:30:56 -07:00
parent 94f7769d6e
commit 3adf33d460
5 changed files with 124 additions and 30 deletions

View File

@ -59,6 +59,11 @@ def build_arg_parser():
"(SSLv3, TLSv1, TLSv1.1, TLSv1.2, TLSv1.3, SSLv23)"
)
parser.add_argument(
"-u", action="store_true",
help="Use UDP DTLS, add -v 0 for DTLSv1, -v 1 for DTLSv1.2 (default)"
)
parser.add_argument(
"-l", metavar="ciphers", type=str, default="",
help="Cipher suite list (: delimited)"
@ -103,7 +108,7 @@ def build_arg_parser():
return parser
def get_method(index):
def get_SSLmethod(index):
return (
wolfssl.PROTOCOL_SSLv3,
wolfssl.PROTOCOL_TLSv1,
@ -113,17 +118,27 @@ def get_method(index):
wolfssl.PROTOCOL_SSLv23
)[index]
def get_DTLSmethod(index):
return (
wolfssl.PROTOCOL_DTLSv1,
wolfssl.PROTOCOL_DTLSv1_2
)[index]
def main():
args = build_arg_parser().parse_args()
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
# DTLS connection over UDP
if args.u:
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
context = wolfssl.SSLContext(get_DTLSmethod(args.v))
# SSL/TLS connection over TCP
else:
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
context = wolfssl.SSLContext(get_SSLmethod(args.v))
# enable debug, if native wolfSSL has been compiled with '--enable-debug'
wolfssl.WolfSSL.enable_debug()
context = wolfssl.SSLContext(get_method(args.v))
context.load_cert_chain(args.c, args.k)
if args.d:

View File

@ -54,6 +54,11 @@ def build_arg_parser():
"(SSLv3, TLSv1, TLSv1.1, TLSv1.2, TLSv1_3, SSLv23)"
)
parser.add_argument(
"-u", action="store_true",
help="Use UDP DTLS, add -v 0 for DTLSv1, -v 1 for DTLSv1.2"
)
parser.add_argument(
"-l", metavar="ciphers", type=str, default="",
help="Cipher suite list (: delimited)"
@ -92,7 +97,7 @@ def build_arg_parser():
return parser
def get_method(index):
def get_SSLmethod(index):
return (
wolfssl.PROTOCOL_SSLv3,
wolfssl.PROTOCOL_TLSv1,
@ -102,21 +107,36 @@ def get_method(index):
wolfssl.PROTOCOL_SSLv23
)[index]
def get_DTLSmethod(index):
return (
wolfssl.PROTOCOL_DTLSv1,
wolfssl.PROTOCOL_DTLSv1_2
)[index]
def main():
args = build_arg_parser().parse_args()
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
bind_socket.bind(("" if args.b else "localhost", args.p))
bind_socket.listen(5)
# DTLS connection over UDP
if args.u:
# Set DTLSv1.2 as default if unspecified
if args.v == 5:
args.v = 1
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
bind_socket.bind(("" if args.b else "localhost", args.p))
data, from_addr = bind_socket.recvfrom(1)
context = wolfssl.SSLContext(get_DTLSmethod(args.v), server_side=True)
# SSL/TLS connection over TCP
else:
bind_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
bind_socket.bind(("" if args.b else "localhost", args.p))
bind_socket.listen(5)
context = wolfssl.SSLContext(get_SSLmethod(args.v), server_side=True)
print("Server listening on port", bind_socket.getsockname()[1])
# enable debug, if native wolfSSL has been compiled with '--enable-debug'
wolfssl.WolfSSL.enable_debug()
context = wolfssl.SSLContext(get_method(args.v), server_side=True)
context.load_cert_chain(args.c, args.k)
if args.d:
@ -131,10 +151,11 @@ def main():
while True:
try:
secure_socket = None
new_socket, from_addr = bind_socket.accept()
secure_socket = context.wrap_socket(new_socket)
if args.u:
secure_socket = context.wrap_socket(bind_socket)
else:
new_socket, from_addr = bind_socket.accept()
secure_socket = context.wrap_socket(new_socket)
print("Connection received from", from_addr)

View File

@ -51,7 +51,8 @@ from wolfssl.exceptions import ( # noqa: F401
from wolfssl._methods import ( # noqa: F401
PROTOCOL_SSLv23, PROTOCOL_SSLv3, PROTOCOL_TLSv1,
PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2, PROTOCOL_TLSv1_3,
PROTOCOL_TLS, WolfSSLMethod as _WolfSSLMethod
PROTOCOL_TLS, PROTOCOL_DTLSv1, PROTOCOL_DTLSv1_2,
WolfSSLMethod as _WolfSSLMethod
)
CERT_NONE = 0
@ -64,6 +65,8 @@ _SSL_FILETYPE_PEM = 1
_SSL_ERROR_WANT_READ = 2
_SSL_ERROR_WANT_WRITE = 3
_SOCKADDR_SZ = 16
_PY3 = sys.version_info[0] == 3
@ -519,7 +522,6 @@ class SSLSocket(object):
"""
Enables CRL certificate revocation
"""
ret = _lib.wolfSSL_EnableCRL(self.native_object, options)
if ret != _SSL_SUCCESS:
@ -529,7 +531,6 @@ class SSLSocket(object):
"""
Load CRL certificate revocation
"""
ret = _lib.wolfSSL_LoadCRLFile(self.native_object,
t2b(path) if path else _ffi.NULL,
filetype)
@ -543,7 +544,12 @@ class SSLSocket(object):
Returns number of bytes of DATA actually transmitted.
"""
self._check_closed("write")
self._check_connected()
# Check connected if not DTLS
if self._context.protocol < PROTOCOL_DTLSv1:
self._check_connected()
# Complete handshake if DTLS connection
else:
self.do_handshake()
data = t2b(data)
@ -599,7 +605,12 @@ class SSLSocket(object):
Return zero-length string on EOF.
"""
self._check_closed("read")
self._check_connected()
# Check connected if not DTLS
if self._context.protocol < PROTOCOL_DTLSv1:
self._check_connected()
# Complete handshake if DTLS connection
else:
self.do_handshake()
if buffer is not None:
raise ValueError("buffer not allowed in calls to "
@ -630,7 +641,8 @@ class SSLSocket(object):
to full size of buffer.
"""
self._check_closed("read")
self._check_connected()
if self._context.protocol < PROTOCOL_DTLSv1:
self._check_connected()
if buffer is None:
raise ValueError("buffer cannot be None")
@ -678,7 +690,8 @@ class SSLSocket(object):
if self.native_object != _ffi.NULL:
_lib.wolfSSL_shutdown(self.native_object)
self._release_native_object()
self._sock.shutdown(how)
if self._context.protocol < PROTOCOL_DTLSv1:
self._sock.shutdown(how)
def unwrap(self):
"""
@ -698,12 +711,23 @@ class SSLSocket(object):
return sock
def add_peer(self, addr):
peerAddr = _lib.wolfSSL_dtls_create_peer(addr[1],t2b(addr[0]))
if peerAddr == _ffi.NULL:
raise SSLError("Failed to create peer")
ret = _lib.wolfSSL_dtls_set_peer(self.native_object, peerAddr,
_SOCKADDR_SZ)
if ret != _SSL_SUCCESS:
raise SSLError("Unable to set dtls peer. E(%d)" % ret)
_lib.wolfSSL_dtls_free_peer(peerAddr)
def do_handshake(self, block=False): # pylint: disable=unused-argument
"""
Perform a TLS/SSL handshake.
"""
self._check_closed("do_handshake")
self._check_connected()
if self._context.protocol < PROTOCOL_DTLSv1:
self._check_connected()
if self._server_side:
ret = _lib.wolfSSL_accept(self.native_object)
@ -756,13 +780,19 @@ class SSLSocket(object):
if self._connected:
raise ValueError("attempt to connect already-connected SSLSocket!")
if connect_ex:
err = self._sock.connect_ex(addr)
err = 0
ret = _SSL_SUCCESS
if self._context.protocol >= PROTOCOL_DTLSv1:
self.add_peer(addr)
else:
err = 0
self._sock.connect(addr)
if connect_ex:
err = self._sock.connect_ex(addr)
else:
err = 0
self._sock.connect(addr)
if err == 0:
if err == 0 and ret == _SSL_SUCCESS:
self._connected = True
if self.do_handshake_on_connect:
self.do_handshake()

View File

@ -156,9 +156,15 @@ def make_flags(prefix, debug):
# tls 1.3
flags.append("--enable-tls13")
# dtls
flags.append("--enable-dtls")
# crl
flags.append("--enable-crl")
# wrapper allocators
cflags.append("-DWOLFSSL_WRAPPER_ALLOCATORS")
# for urllib3 - requires SNI (tlsx), options (openssl compat), peer cert
flags.append("--enable-tlsx")
flags.append("--enable-opensslextra")
@ -202,7 +208,7 @@ def make(configure_flags):
call("make install")
def build_wolfssl(ref, debug=False):
def build_wolfssl(ref, debug=True):
prefix = local_path("lib/wolfssl/{}/{}".format(
get_platform(), ref))
libfile = os.path.join(prefix, 'lib/libwolfssl.la')
@ -394,6 +400,12 @@ cdef += """
WOLFSSL_METHOD* wolfSSLv23_client_method(void);
WOLFSSL_METHOD* wolfSSLv23_method(void);
WOLFSSL_METHOD* wolfDTLSv1_server_method(void);
WOLFSSL_METHOD* wolfDTLSv1_client_method(void);
WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void);
WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void);
"""
if OLDTLS_ENABLED:
cdef += """
@ -453,6 +465,9 @@ cdef += """
void wolfSSL_set_connect_state(WOLFSSL*);
int wolfSSL_EnableCRL(WOLFSSL*, int);
int wolfSSL_LoadCRLFile(WOLFSSL*, const char*, int);
void* wolfSSL_dtls_create_peer(int, char*);
int wolfSSL_dtls_free_peer(void*);
int wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int);
/**
* WOLFSSL_X509 functions

View File

@ -36,10 +36,12 @@ PROTOCOL_TLSv1 = 3
PROTOCOL_TLSv1_1 = 4
PROTOCOL_TLSv1_2 = 5
PROTOCOL_TLSv1_3 = 6
PROTOCOL_DTLSv1 = 7
PROTOCOL_DTLSv1_2 = 8
_PROTOCOL_LIST = [PROTOCOL_SSLv23, PROTOCOL_SSLv3, PROTOCOL_TLS,
PROTOCOL_TLSv1, PROTOCOL_TLSv1_1, PROTOCOL_TLSv1_2,
PROTOCOL_TLSv1_3]
PROTOCOL_TLSv1_3, PROTOCOL_DTLSv1, PROTOCOL_DTLSv1_2]
_DYNAMIC_TYPE_METHOD = 11
@ -86,6 +88,17 @@ class WolfSSLMethod(object): # pylint: disable=too-few-public-methods
_lib.wolfSSLv23_server_method() if server_side else \
_lib.wolfSSLv23_client_method()
elif protocol == PROTOCOL_DTLSv1:
self.native_object = \
_lib.wolfDTLSv1_server_method() if server_side else \
_lib.wolfDTLSv1_client_method()
elif protocol == PROTOCOL_DTLSv1_2:
self.native_object = \
_lib.wolfDTLSv1_2_server_method() if server_side else \
_lib.wolfDTLSv1_2_client_method()
if self.native_object == _ffi.NULL:
raise MemoryError("Unnable to allocate method object")