From 60f3975029f6f05164dbe23374579a384080e311 Mon Sep 17 00:00:00 2001 From: Gergo Ujhelyi Date: Fri, 24 Jun 2022 13:58:25 +0200 Subject: [PATCH 1/4] update copyright date Signed-off-by: Gergo Ujhelyi --- .../user_provided/Abstract_Socket.java | 2 +- .../user_provided/PacketHeaderDescr.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java index c33e51a..1d34e86 100644 --- a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java +++ b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java @@ -1,5 +1,5 @@ /****************************************************************************** - * Copyright (c) 2000-2021 Ericsson Telecom AB + * Copyright (c) 2000-2022 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at diff --git a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/PacketHeaderDescr.java b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/PacketHeaderDescr.java index 35f491c..b63fcf2 100644 --- a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/PacketHeaderDescr.java +++ b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/PacketHeaderDescr.java @@ -1,10 +1,10 @@ /****************************************************************************** -* Copyright (c) 2000-2021 Ericsson Telecom AB -* All rights reserved. This program and the accompanying materials -* are made available under the terms of the Eclipse Public License v2.0 -* which accompanies this distribution, and is available at -* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html -******************************************************************************/ + * Copyright (c) 2000-2022 Ericsson Telecom AB + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html + ******************************************************************************/ package org.eclipse.titan.titan_JavaTestPorts_Common_Components_Abstract_Socket.user_provided; /******************************** -- GitLab From a740a143a878901e99b92869a7a25a8406d8c0cf Mon Sep 17 00:00:00 2001 From: Gergo Ujhelyi Date: Fri, 24 Jun 2022 19:25:23 +0200 Subject: [PATCH 2/4] add the necessary ssl member variables Signed-off-by: Gergo Ujhelyi --- .../user_provided/Abstract_Socket.java | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java index 1d34e86..e59442f 100644 --- a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java +++ b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java @@ -21,8 +21,15 @@ import java.nio.channels.SelectableChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.UnresolvedAddressException; +import java.security.KeyStore; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLSession; import org.eclipse.titan.runtime.core.TTCN_Buffer; import org.eclipse.titan.runtime.core.TTCN_Logger; @@ -44,6 +51,12 @@ public abstract class Abstract_Socket { private static final int NI_MAXSERV = 32; + // SSLContext Algorithms + public static final String TLS13 = "TLSv1.3"; // Recommended to use !!! Supports RFC 8446: TLS version 1.3; may support other SSL/TLS versions. + public static final String TLS12 = "TLSv1.2"; // Supports RFC 5246: TLS version 1.2; may support other SSL/TLS versions. + public static final String SSLv3 = "SSLv3"; // Supports SSL version 3; may support other SSL/TLS versions. + public static final String SSLv2 = "SSLv2"; // Supports SSL version 2 or later; may support other SSL/TLS versions. + private boolean halt_on_connection_reset_set; private boolean halt_on_connection_reset; private boolean client_TCP_reconnect; @@ -68,6 +81,29 @@ public abstract class Abstract_Socket { private List peer_list_root; + //SSL related member variables + private SSLContext sslContext; + private SSLEngine sslEngine; + private SSLSession sslSession; + + private KeyStore sslKeyFile; // KeyStore + private KeyStore sslTrustedFile; // TrustStore + + private ByteBuffer myAppData; + private ByteBuffer myNetData; + private ByteBuffer peerAppData; + private ByteBuffer peerNetData; + + private String keyStorePassword; + private String trustStorePassword; + + + // Executor for SSL handshake tasks + // TODO: Check running time with other executors + private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); + + //TODO: more member variables needed for testport parameters + /******************************** ** Abstract_Socket ** abstract base type for TCP socket handling @@ -1170,8 +1206,6 @@ public abstract class Abstract_Socket { protected String ssl_verifycertificate_name() { return "ssl_verify_certificate";} protected String ssl_disable_SSLv2() { return "ssl_disable_SSLv2";} protected String ssl_disable_SSLv3() { return "ssl_disable_SSLv3";} - protected String ssl_disable_TLSv1() { return "ssl_disable_TLSv1";} - protected String ssl_disable_TLSv1_1() { return "ssl_disable_TLSv1_1";} protected String ssl_disable_TLSv1_2() { return "ssl_disable_TLSv1_2";} protected String ssl_disable_TLSv1_3() { return "ssl_disable_TLSv1_3";} protected String ssl_keystore_type() { return "ssl_keystore_type";} -- GitLab From 4d013e696b2fee3e3298e6b99af5fca65388afed Mon Sep 17 00:00:00 2001 From: Gergo Ujhelyi Date: Thu, 30 Jun 2022 13:03:23 +0200 Subject: [PATCH 3/4] beginnig of the keystore utility functions Signed-off-by: Gergo Ujhelyi --- .../user_provided/Abstract_Socket.java | 93 ++++++++++++++++++- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java index e59442f..0674724 100644 --- a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java +++ b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java @@ -7,6 +7,9 @@ ******************************************************************************/ package org.eclipse.titan.titan_JavaTestPorts_Common_Components_Abstract_Socket.user_provided; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.net.Inet4Address; import java.net.Inet6Address; @@ -22,6 +25,9 @@ import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.UnresolvedAddressException; import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; @@ -56,7 +62,20 @@ public abstract class Abstract_Socket { public static final String TLS12 = "TLSv1.2"; // Supports RFC 5246: TLS version 1.2; may support other SSL/TLS versions. public static final String SSLv3 = "SSLv3"; // Supports SSL version 3; may support other SSL/TLS versions. public static final String SSLv2 = "SSLv2"; // Supports SSL version 2 or later; may support other SSL/TLS versions. - + + /* + * Default KeyStore directory. + * + * The default is working directory / resources / ssl + */ + private static final String DEFAULT_KEYSTORE_DIRECTORY = System.getProperty("user.dir") + File.pathSeparator + "resources" + File.pathSeparator + "ssl" + File.pathSeparator; + + private static final String DEFAULT_KEYSTORE_PASSWORD = "changeme"; + + private static final String DEFAULT_KEYSTORE_FILE_NAME = "sslKeyStore"; + + private static final String DEFAULT_TRUSTSTORE_FILE_NAME = "sslTrustedKeyStore"; + private boolean halt_on_connection_reset_set; private boolean halt_on_connection_reset; private boolean client_TCP_reconnect; @@ -97,10 +116,15 @@ public abstract class Abstract_Socket { private String keyStorePassword; private String trustStorePassword; + private boolean ssl_verify_certificate; // Configures the engine to request client authentication. + private boolean ssl_use_ssl; // Whether to use SSL. + private boolean ssl_initialized; // Whether SSL already initialized or not. + private List ssl_cipher_list; // SSL cipher list restriction to apply. + private String ssl_password; // Password to decode the private key. // Executor for SSL handshake tasks // TODO: Check running time with other executors - private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor(); + private ExecutorService singleThreadExecutor; //TODO: more member variables needed for testport parameters @@ -129,6 +153,15 @@ public abstract class Abstract_Socket { use_connection_ASPs = false; handle_half_close = false; peer_list_root = null; + + ssl_use_ssl = false; + ssl_initialized = false; + sslKeyFile = null; + sslTrustedFile = null; + ssl_verify_certificate = false; + ssl_cipher_list = null; + ssl_password = null; + singleThreadExecutor = Executors.newSingleThreadExecutor(); } public Abstract_Socket(String test_port_type, String test_port_name) { @@ -152,6 +185,15 @@ public abstract class Abstract_Socket { use_connection_ASPs = false; handle_half_close = false; peer_list_root = null; + + ssl_use_ssl = false; + ssl_initialized = false; + sslKeyFile = null; + sslTrustedFile = null; + ssl_verify_certificate = false; + ssl_cipher_list = null; + ssl_password = null; + singleThreadExecutor = Executors.newSingleThreadExecutor(); } //////////////////////////////////////////////////////////////////////// @@ -463,7 +505,7 @@ public abstract class Abstract_Socket { } /** - * Called after a peer is connectedd + * Called after a peer is connected * * Do nothing in here. Override in your testport implementation. * @@ -1208,7 +1250,6 @@ public abstract class Abstract_Socket { protected String ssl_disable_SSLv3() { return "ssl_disable_SSLv3";} protected String ssl_disable_TLSv1_2() { return "ssl_disable_TLSv1_2";} protected String ssl_disable_TLSv1_3() { return "ssl_disable_TLSv1_3";} - protected String ssl_keystore_type() { return "ssl_keystore_type";} protected boolean add_user_data(SelectableChannel id) { return true; @@ -1347,6 +1388,50 @@ public abstract class Abstract_Socket { protected abstract void Remove_Fd_Write_Handler(SelectableChannel fd); protected abstract void Remove_Fd_All_Handlers(SelectableChannel fd); protected abstract void Handler_Uninstall(); + + private KeyStore initKeyStore(final String filePath, final String password) { + return initKeyStore(filePath, password, KeyStore.getDefaultType()); + } + + //TODO: finish function and return ks variable at the end + private KeyStore initKeyStore(final String filePath, final String password, final String keyStoreType) { + boolean defaultFilePath = false; + boolean defaultPassword = false; + boolean defaultKeyStoreType = false; + + if (filePath == null || filePath.isEmpty()) { + TtcnError.TtcnWarning("Invalid KeyStore file path! Using the default file path."); + defaultFilePath = true; + } + if (password == null || password.isEmpty()) { + TtcnError.TtcnWarning("Invalid KeyStore password! Using the default password."); + defaultPassword = true; + } + if (keyStoreType == null || keyStoreType.isEmpty()) { + TtcnError.TtcnWarning("Invalid KeyStore type! Using the default type."); + defaultKeyStoreType = true; + } + KeyStore ks = null; + try { + ks = defaultKeyStoreType ? KeyStore.getInstance(KeyStore.getDefaultType()) : KeyStore.getInstance(keyStoreType); + } catch (KeyStoreException e) { + throw new TtcnError(e.getMessage()); + } + File keyFile = new File(filePath); + if (!keyFile.exists()) { + try { + ks.load(null, defaultPassword ? DEFAULT_KEYSTORE_PASSWORD.toCharArray() : password.toCharArray()); + } catch (NoSuchAlgorithmException e) { + throw new TtcnError(e.getMessage()); + } catch (CertificateException e) { + throw new TtcnError(e.getMessage()); + } catch (IOException e) { + throw new TtcnError(e.getMessage()); + } + // TODO: finish create key file + } + return null; + } public static class as_client_struct { // proper implementation of void* type -- GitLab From 31086f57f1fe345e46526784e8d4261b902d7039 Mon Sep 17 00:00:00 2001 From: Gergo Ujhelyi Date: Thu, 30 Jun 2022 13:05:53 +0200 Subject: [PATCH 4/4] better handshake function Signed-off-by: Gergo Ujhelyi --- .../user_provided/Abstract_Socket.java | 107 ++++++++++++++++-- 1 file changed, 100 insertions(+), 7 deletions(-) diff --git a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java index 0674724..5f86e46 100644 --- a/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java +++ b/JavaTestPorts/titan.JavaTestPorts.Common_Components.Abstract_Socket/user_provided/org/eclipse/titan/titan_JavaTestPorts_Common_Components_Abstract_Socket/user_provided/Abstract_Socket.java @@ -35,7 +35,9 @@ import java.util.concurrent.Executors; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; import org.eclipse.titan.runtime.core.TTCN_Buffer; import org.eclipse.titan.runtime.core.TTCN_Logger; @@ -62,7 +64,7 @@ public abstract class Abstract_Socket { public static final String TLS12 = "TLSv1.2"; // Supports RFC 5246: TLS version 1.2; may support other SSL/TLS versions. public static final String SSLv3 = "SSLv3"; // Supports SSL version 3; may support other SSL/TLS versions. public static final String SSLv2 = "SSLv2"; // Supports SSL version 2 or later; may support other SSL/TLS versions. - + /* * Default KeyStore directory. * @@ -71,11 +73,11 @@ public abstract class Abstract_Socket { private static final String DEFAULT_KEYSTORE_DIRECTORY = System.getProperty("user.dir") + File.pathSeparator + "resources" + File.pathSeparator + "ssl" + File.pathSeparator; private static final String DEFAULT_KEYSTORE_PASSWORD = "changeme"; - + private static final String DEFAULT_KEYSTORE_FILE_NAME = "sslKeyStore"; - + private static final String DEFAULT_TRUSTSTORE_FILE_NAME = "sslTrustedKeyStore"; - + private boolean halt_on_connection_reset_set; private boolean halt_on_connection_reset; private boolean client_TCP_reconnect; @@ -1388,17 +1390,17 @@ public abstract class Abstract_Socket { protected abstract void Remove_Fd_Write_Handler(SelectableChannel fd); protected abstract void Remove_Fd_All_Handlers(SelectableChannel fd); protected abstract void Handler_Uninstall(); - + private KeyStore initKeyStore(final String filePath, final String password) { return initKeyStore(filePath, password, KeyStore.getDefaultType()); } - + //TODO: finish function and return ks variable at the end private KeyStore initKeyStore(final String filePath, final String password, final String keyStoreType) { boolean defaultFilePath = false; boolean defaultPassword = false; boolean defaultKeyStoreType = false; - + if (filePath == null || filePath.isEmpty()) { TtcnError.TtcnWarning("Invalid KeyStore file path! Using the default file path."); defaultFilePath = true; @@ -1433,6 +1435,97 @@ public abstract class Abstract_Socket { return null; } + private void sslHandshake(final SocketChannel socketChannel) throws IOException { + SSLEngineResult result = null; + SSLEngineResult.HandshakeStatus handshakeStatus = null; + final int applicationBufferSize = sslSession.getApplicationBufferSize(); + + ByteBuffer myAppData = ByteBuffer.allocate(applicationBufferSize); + ByteBuffer peerAppData = ByteBuffer.allocate(applicationBufferSize); + + sslEngine.beginHandshake(); + + handshakeStatus = sslEngine.getHandshakeStatus(); + + while (handshakeStatus != HandshakeStatus.FINISHED && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) { + switch (handshakeStatus) { + case NEED_UNWRAP: + if (socketChannel.read(peerNetData) < 0) { + // TODO close connection properly + } + peerNetData.flip(); + result = sslEngine.unwrap(peerNetData, peerAppData); + peerNetData.compact(); + handshakeStatus = result.getHandshakeStatus(); + // Check status + switch (result.getStatus()) { + case OK: + // Nothing done + break; + case BUFFER_UNDERFLOW: + if (sslEngine.getSession().getPacketBufferSize() > peerNetData.capacity()) { + peerNetData = ByteBuffer.allocate(sslSession.getPacketBufferSize()); + } else { + peerNetData.clear(); + } + break; + case BUFFER_OVERFLOW: + if (sslEngine.getSession().getApplicationBufferSize() > peerAppData.capacity()) { + peerAppData = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize()); + } else { + peerAppData.clear(); + } + break; + case CLOSED: + if (!sslEngine.isOutboundDone()) { + sslEngine.closeOutbound(); + handshakeStatus = sslEngine.getHandshakeStatus(); + } + break; + default: + throw new IllegalStateException("Invalid SSLEngineResult status"); + } + break; + case NEED_WRAP: + myNetData.clear(); + result = sslEngine.wrap(myAppData, myNetData); + handshakeStatus = result.getHandshakeStatus(); + // Check status + switch (result.getStatus()) { + case OK: + myNetData.flip(); + while (myNetData.hasRemaining()) { + socketChannel.write(myNetData); + } + break; + case BUFFER_OVERFLOW: + // TODO implement + break; + case BUFFER_UNDERFLOW: + // TODO implement + break; + case CLOSED: + // TODO implement + break; + default: + break; + } + break; + case NEED_TASK: + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = sslEngine.getDelegatedTask()) != null) { + singleThreadExecutor.execute(runnable); + } + handshakeStatus = sslEngine.getHandshakeStatus(); + } + break; + default: + break; + } + } + } + public static class as_client_struct { // proper implementation of void* type public Object user_data; -- GitLab