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: