RISE-V2G/RISE-V2G-SECC/src/main/java/com/v2gclarity/risev2g/secc/transportLayer/TLSServer.java

160 lines
5.9 KiB
Java
Raw Normal View History

2015-06-01 08:19:09 -07:00
/*******************************************************************************
* The MIT License (MIT)
2015-06-01 08:19:09 -07:00
*
* Copyright (c) 2015-207 V2G Clarity (Dr.-Ing. Marc Mültin)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
2015-06-01 08:19:09 -07:00
*******************************************************************************/
package com.v2gclarity.risev2g.secc.transportLayer;
2015-06-01 08:19:09 -07:00
import java.io.IOException;
import java.net.SocketException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import com.v2gclarity.risev2g.shared.enumerations.GlobalValues;
import com.v2gclarity.risev2g.shared.utils.SecurityUtils;
2015-06-01 08:19:09 -07:00
public final class TLSServer extends StatefulTransportLayerServer {
private static final TLSServer uniqueTLSServerInstance = new TLSServer();
private SSLSocket tlsClientSocket;
private SSLServerSocket tlsServerSocket;
private TLSServer() {}
public static TLSServer getInstance() {
return uniqueTLSServerInstance;
}
/**
* Used to check the correct initialization of a TCP server which is a prerequisite for establishing
* a V2G communication session.
* @return True if the initialization of the TCP server was successful, false otherwise
*/
public boolean initialize() {
super.initialize();
try {
/*
* Setting the system property for the keystore and truststore via
* - System.setProperty("javax.net.ssl.keyStore", [filePath given as a String])
* - System.setProperty("javax.net.ssl.trustStore", [filePath given as a String])
* does not work in a JAR file since only getResourceAsStream works there (which on the other
* hand only returns an InputStream, not a file resource). Thus use setSSLContext()
2015-06-01 08:19:09 -07:00
*/
2015-06-01 08:19:09 -07:00
SecurityUtils.setSSLContext(
GlobalValues.SECC_KEYSTORE_FILEPATH.toString(),
GlobalValues.SECC_TRUSTSTORE_FILEPATH.toString(),
GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString());
2015-06-01 08:19:09 -07:00
SSLServerSocketFactory tlsServerSocketFactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
setTlsServerSocket((SSLServerSocket) tlsServerSocketFactory
.createServerSocket(getServerPort(), 50, getServerAddress()));
/*
* The EVCC shall support at least one cipher suite as listed below according to
* the standard. An implementer may decide to choose only one of them:
* - TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
* - TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
*/
String[] enabledCipherSuites = {
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
"TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256"
};
2015-06-01 08:19:09 -07:00
getTlsServerSocket().setEnabledCipherSuites(enabledCipherSuites);
// Set the supported TLS protocol
String[] enabledProtocols = {"TLSv1.2"};
getTlsServerSocket().setEnabledProtocols(enabledProtocols);
Changelog commit 15.9.17 - Added copyNewCertsAndKeys.bat and generateCertificates.bat to RISE-V2G-Certificates in order to port the already existing Unix shell scripts to Windows systems - Corrected an error in V2GCommunicationSessionHandlerEVCC.java which ensures that the SDP procedure continues to work correctly even if there is a false SDP response coming from the SECC - Changed the signature of the method generateDigest() (in SecurityUtils.java) to have more logging information about the ID of the element for which the digest is generated - Made sure that the PreCharge timeout and CableCheck timeout are triggered exactly (there was a possible delay of 2s) - Changed logging level of TCP server and client from debug to info - Added debugging logging functionality with new EVCC and SECC property HexAndBase64RepresentationOfMessages which will log the hexadecimal and Base64 encoding of each message being sent - Small change in log4j2.xml files enabling highlighting of logging level (you need to have ANSI Console installed in Eclipse IDE for this change to take effect) - Shifted the process of reading the MO Sub-CA 2 private key from the keystore from the method getMOSubCA2PrivateKey to the constructor of DummyBackendInterface.java in order to avoid timeouts when processing the ChargeParameterDiscoveryReq on embedded devices - Updated the EXIficient_V2G_CI_MsgDef.java (serialized version of the XSD grammar) as there was an bug before that caused an incomplete deserialization of an EXI byte stream to an XML message - Updated log4j from 2.1 to 2.9
2017-09-15 07:15:25 -07:00
getLogger().info("TLS server initialized at link-local address " +
2015-06-01 08:19:09 -07:00
getTlsServerSocket().getInetAddress().getHostAddress() +
" and port " + getTlsServerSocket().getLocalPort());
} catch (IOException e) {
getLogger().fatal("IOException while trying to initialize TLS server", e);
return false;
} catch (NullPointerException e) {
getLogger().fatal("NullPointerException while trying to set keystores, resource path to keystore/truststore might be incorrect");
return false;
}
return true;
}
@Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
Changelog commit 15.9.17 - Added copyNewCertsAndKeys.bat and generateCertificates.bat to RISE-V2G-Certificates in order to port the already existing Unix shell scripts to Windows systems - Corrected an error in V2GCommunicationSessionHandlerEVCC.java which ensures that the SDP procedure continues to work correctly even if there is a false SDP response coming from the SECC - Changed the signature of the method generateDigest() (in SecurityUtils.java) to have more logging information about the ID of the element for which the digest is generated - Made sure that the PreCharge timeout and CableCheck timeout are triggered exactly (there was a possible delay of 2s) - Changed logging level of TCP server and client from debug to info - Added debugging logging functionality with new EVCC and SECC property HexAndBase64RepresentationOfMessages which will log the hexadecimal and Base64 encoding of each message being sent - Small change in log4j2.xml files enabling highlighting of logging level (you need to have ANSI Console installed in Eclipse IDE for this change to take effect) - Shifted the process of reading the MO Sub-CA 2 private key from the keystore from the method getMOSubCA2PrivateKey to the constructor of DummyBackendInterface.java in order to avoid timeouts when processing the ChargeParameterDiscoveryReq on embedded devices - Updated the EXIficient_V2G_CI_MsgDef.java (serialized version of the XSD grammar) as there was an bug before that caused an incomplete deserialization of an EXI byte stream to an XML message - Updated log4j from 2.1 to 2.9
2017-09-15 07:15:25 -07:00
getLogger().info("Waiting for new TLS client connection ...");
2015-06-01 08:19:09 -07:00
setTlsClientSocket((SSLSocket) getTlsServerSocket().accept());
Changelog commit 15.9.17 - Added copyNewCertsAndKeys.bat and generateCertificates.bat to RISE-V2G-Certificates in order to port the already existing Unix shell scripts to Windows systems - Corrected an error in V2GCommunicationSessionHandlerEVCC.java which ensures that the SDP procedure continues to work correctly even if there is a false SDP response coming from the SECC - Changed the signature of the method generateDigest() (in SecurityUtils.java) to have more logging information about the ID of the element for which the digest is generated - Made sure that the PreCharge timeout and CableCheck timeout are triggered exactly (there was a possible delay of 2s) - Changed logging level of TCP server and client from debug to info - Added debugging logging functionality with new EVCC and SECC property HexAndBase64RepresentationOfMessages which will log the hexadecimal and Base64 encoding of each message being sent - Small change in log4j2.xml files enabling highlighting of logging level (you need to have ANSI Console installed in Eclipse IDE for this change to take effect) - Shifted the process of reading the MO Sub-CA 2 private key from the keystore from the method getMOSubCA2PrivateKey to the constructor of DummyBackendInterface.java in order to avoid timeouts when processing the ChargeParameterDiscoveryReq on embedded devices - Updated the EXIficient_V2G_CI_MsgDef.java (serialized version of the XSD grammar) as there was an bug before that caused an incomplete deserialization of an EXI byte stream to an XML message - Updated log4j from 2.1 to 2.9
2017-09-15 07:15:25 -07:00
getLogger().info("TLS client connection with IP address " +
2015-06-01 08:19:09 -07:00
getTlsClientSocket().getInetAddress().getHostAddress() + " and port " +
getTlsClientSocket().getPort());
2015-06-01 08:19:09 -07:00
ConnectionHandler connectionHandler = new ConnectionHandler(tlsClientSocket);
Commit-Nachricht für RISE V2G - Signature creation and verification has been fixed and works now properly. Has been tested against various industry OEMs and suppliers.
SecurityUtils.java class was substantially revised as part of fixing the signature creation and verification process and extended signature logging - Introduced a new abstract method setMandatoryFieldsForFailedRes() in ServerState which makes sure that for each response the mandatory fields are set properly according to the standard in case a FAILED response code is sent - Introduced a fix in WaitForAuthorizationReq which makes sure that a possible challenge is only checked for if the chosen payment option is „Contract“ (and TLS is used) - Saves now the payment option selected by the EVCC (in state WaitForPaymentServiceSelectionReq) in the SECCs communication session for later reference - To avoid possible race conditions, the transport layer threads needed to be started AFTER the SECC session handler has been initialized. Otherwise the situation might occur that the UDPServer is receiving a UDP client packet and tries to access the MessageHandler object before this object has been created by the SECC session handler. - generateCertificates.sh Shell-Script now includes variables to ease the setting of certificates’ validity periods. Renaming of some certificates (e.g. provLeaf.cert -> cpsLeaf.cert) and keys. All certificates are now also generated in DER encoded form. MOSubCA2 private key is now also created as a PKCS#8 DER encoded file as RISE V2G needs this format to read the private key from file and sign SalesTariffs. - EVCCConfig.properties and SECCConfig.properties have additional property „SignatureVerificationLog“ which enables extended logging information to debug signature creation and verification processes - Catched a (theoretically) possible ClassCastException in WaitForChargeParameterDiscoveryRes in case the EVCC signalizes an EnergyTransferMode (AC or DC) which does not fit to the EVSEChargeParameter sent by the SECC later on - Made sure that by default the sum of the individual time intervals described in the PMaxSchedule and SalesTariff provided in the ChargeParameterDiscoveryRes message are equal to 24 hours as demanded by a requirement. - Renaming of some methods in IBackendInterface for clarity and consistency - Provided a correctly formatted EVSE-ID in DummyACEVSEController and DummyDCEVSEController - Corrected the service name of CertificateUpdate service and CertificateInstallation service to „Service“ according to the standard - Edited GlobalValues so that the string value returned for each global value only needs to be edited once in this file (less error prone)
2017-07-20 06:50:43 -07:00
// Notify the V2GCommunicationSessionHandlerSECC about a newly connected TLS client socket
2015-06-01 08:19:09 -07:00
setChanged();
notifyObservers(connectionHandler);
}
} catch (IOException e) {
getLogger().error(e.getClass().getSimpleName() + " occurred while running TLSServer");
} finally {
stop();
}
}
@Override
public void stop() {
try {
getLogger().debug("TLS server will be stopped now");
getTlsServerSocket().close();
} catch (SocketException e) {
getLogger().debug("TLSServerSocket was still active and has been closed now", e);
} catch (IOException e) {
getLogger().error("Error occurred while trying to close TLSServerSocket (IOException)", e);
}
Commit-Nachricht für RISE V2G - Signature creation and verification has been fixed and works now properly. Has been tested against various industry OEMs and suppliers.
SecurityUtils.java class was substantially revised as part of fixing the signature creation and verification process and extended signature logging - Introduced a new abstract method setMandatoryFieldsForFailedRes() in ServerState which makes sure that for each response the mandatory fields are set properly according to the standard in case a FAILED response code is sent - Introduced a fix in WaitForAuthorizationReq which makes sure that a possible challenge is only checked for if the chosen payment option is „Contract“ (and TLS is used) - Saves now the payment option selected by the EVCC (in state WaitForPaymentServiceSelectionReq) in the SECCs communication session for later reference - To avoid possible race conditions, the transport layer threads needed to be started AFTER the SECC session handler has been initialized. Otherwise the situation might occur that the UDPServer is receiving a UDP client packet and tries to access the MessageHandler object before this object has been created by the SECC session handler. - generateCertificates.sh Shell-Script now includes variables to ease the setting of certificates’ validity periods. Renaming of some certificates (e.g. provLeaf.cert -> cpsLeaf.cert) and keys. All certificates are now also generated in DER encoded form. MOSubCA2 private key is now also created as a PKCS#8 DER encoded file as RISE V2G needs this format to read the private key from file and sign SalesTariffs. - EVCCConfig.properties and SECCConfig.properties have additional property „SignatureVerificationLog“ which enables extended logging information to debug signature creation and verification processes - Catched a (theoretically) possible ClassCastException in WaitForChargeParameterDiscoveryRes in case the EVCC signalizes an EnergyTransferMode (AC or DC) which does not fit to the EVSEChargeParameter sent by the SECC later on - Made sure that by default the sum of the individual time intervals described in the PMaxSchedule and SalesTariff provided in the ChargeParameterDiscoveryRes message are equal to 24 hours as demanded by a requirement. - Renaming of some methods in IBackendInterface for clarity and consistency - Provided a correctly formatted EVSE-ID in DummyACEVSEController and DummyDCEVSEController - Corrected the service name of CertificateUpdate service and CertificateInstallation service to „Service“ according to the standard - Edited GlobalValues so that the string value returned for each global value only needs to be edited once in this file (less error prone)
2017-07-20 06:50:43 -07:00
getLogger().debug("TLS server stopped");
2015-06-01 08:19:09 -07:00
}
public SSLSocket getTlsClientSocket() {
return tlsClientSocket;
}
public void setTlsClientSocket(SSLSocket tlsClientSocket) {
this.tlsClientSocket = tlsClientSocket;
}
public SSLServerSocket getTlsServerSocket() {
return tlsServerSocket;
}
public void setTlsServerSocket(SSLServerSocket tlsServerSocket) {
this.tlsServerSocket = tlsServerSocket;
}
}