edouard@3884: #!/usr/bin/env python edouard@3884: # -*- coding: utf-8 -*- edouard@3884: edouard@3908: # Written by Edouard TISSERANT (C) 2024 edouard@3908: # This file is part of Beremiz IDE edouard@3884: # See COPYING file for copyrights details. edouard@3884: edouard@3884: edouard@3884: """ edouard@3884: The TLS-PSK adapter that handles SSL connections instead of regular sockets, edouard@3884: but using Pre Shared Keys instead of Certificates edouard@3908: edouard@3908: Corresponding stunnel.conf on PLC side: edouard@3908: edouard@3908: [ERPCPSK] edouard@3908: accept = 4000 edouard@3908: connect = 127.0.0.1:3000 edouard@3908: ciphers = PSK edouard@3908: sslVersion = TLSv1.2 edouard@3908: PSKsecrets = psk.txt edouard@3908: edouard@3884: """ edouard@3884: edouard@3884: import socket edouard@3884: import ssl edouard@3884: edouard@3884: try: edouard@3884: import sslpsk edouard@3884: except ImportError as e: edouard@3884: sslpsk = None edouard@3884: edouard@3884: from erpc.transport import TCPTransport edouard@3884: edouard@3884: class SSLPSKClientTransport(TCPTransport): edouard@3884: def __init__(self, host, port, psk): edouard@3884: """ overrides TCPTransport's __init__ to wrap socket in SSl wrapper """ edouard@3884: super(TCPTransport, self).__init__() edouard@3884: self._host = host edouard@3884: self._port = port edouard@3884: self._sock = None edouard@3908: self._isServer = False edouard@3884: edouard@3884: if sslpsk is None: edouard@3884: raise ImportError("sslpsk module is not available") edouard@3884: edouard@3908: self.sslpskctx = sslpsk.SSLPSKContext(ssl.PROTOCOL_TLSv1_2) edouard@3908: self.sslpskctx.set_ciphers('PSK') edouard@3908: self.sslpskctx.psk = psk edouard@3908: edouard@3884: raw_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) edouard@3884: raw_sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) edouard@3884: raw_sock.connect((self._host, self._port)) edouard@3908: edouard@3908: self._sock = self.sslpskctx.wrap_socket(raw_sock, server_side=False) edouard@3884: edouard@3884: