Jelajahi Sumber

Changes/bugfixes due to experience in 4th International Testing Symposium in San Diego, California (April 2016)
- shortend all IDs of reference signature headers to 3 characters like the example given in Annex J (because some embedded systems might restrict the length to 3 characters)
- SecurityUtils: minor additional checks in verifySignature() method
- avoided NullPointerException when incoming message does not have ISO 15118 schema (for example DINSPEC 70121 XSD schema for DC charging)
- made sure optional parameters of ServiceDiscoveryRes are not empty when sent
- added logging message which shows which payment option was chosen by EVCC
- added optional parameter EVSEIsolationStatus in DCEVSEStatus as some EVCC systems tend to need this value according to testival
- bug fix: applied correct private key for signing sales tariff (must be MOSub2CA private key)
- made sure EVCC does not choose contract based payment if SECC offers it although no TLS communication is set up

Marc Mültin 9 tahun lalu
induk
melakukan
6345846e7b
20 mengubah file dengan 148 tambahan dan 37 penghapusan
  1. 1 1
      RISE-V2G-EVCC/EVCCConfig.properties
  2. 6 4
      RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/evController/DummyEVController.java
  3. 7 1
      RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/ClientState.java
  4. 1 1
      RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForChargeParameterDiscoveryRes.java
  5. 7 1
      RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForChargingStatusRes.java
  6. 7 1
      RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForCurrentDemandRes.java
  7. 1 0
      RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForPaymentDetailsRes.java
  8. 14 2
      RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForPaymentServiceSelectionRes.java
  9. 7 1
      RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForServiceDiscoveryRes.java
  10. 24 6
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/backend/DummyBackendInterface.java
  11. 2 1
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/evseController/DummyDCEVSEController.java
  12. 1 1
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/session/V2GCommunicationSessionHandlerSECC.java
  13. 2 0
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForAuthorizationReq.java
  14. 10 4
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForCertificateInstallationReq.java
  15. 10 4
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForCertificateUpdateReq.java
  16. 3 0
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForPaymentServiceSelectionReq.java
  17. 13 2
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForServiceDiscoveryReq.java
  18. 9 1
      RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForSupportedAppProtocolReq.java
  19. 1 1
      RISE-V2G-Shared/src/main/java/org/eclipse/risev2g/shared/utils/MiscUtils.java
  20. 22 5
      RISE-V2G-Shared/src/main/java/org/eclipse/risev2g/shared/utils/SecurityUtils.java

+ 1 - 1
RISE-V2G-EVCC/EVCCConfig.properties

@@ -68,7 +68,7 @@ RequestedPaymentOption =
 # - DC_extended
 # - DC_combo_core
 # - DC_unique
-RequestedEnergyTransferMode = AC_three_phase_core
+RequestedEnergyTransferMode = 
 
 
 # XML representation of messages

+ 6 - 4
RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/evController/DummyEVController.java

@@ -48,10 +48,12 @@ public class DummyEVController implements IACEVController, IDCEVController {
 	
 	@Override
 	public PaymentOptionType getPaymentOption(PaymentOptionListType paymentOptionsOffered) {
-		if (paymentOptionsOffered.getPaymentOption().contains(PaymentOptionType.CONTRACT))
-			return PaymentOptionType.CONTRACT; 
-		else 
-			return PaymentOptionType.EXTERNAL_PAYMENT;
+		if (paymentOptionsOffered.getPaymentOption().contains(PaymentOptionType.CONTRACT)) {
+			if (!getCommSessionContext().isTlsConnection()) {
+				getLogger().warn("SECC offered CONTRACT based payment although no TLS connectionis used. Choosing EIM instead");
+				return PaymentOptionType.EXTERNAL_PAYMENT;
+			} else return PaymentOptionType.CONTRACT; 
+		} else return PaymentOptionType.EXTERNAL_PAYMENT;
 	}
 
 

+ 7 - 1
RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/ClientState.java

@@ -253,7 +253,13 @@ public abstract class ClientState extends State {
 		
 		if (genChallenge != null) {
 			authorizationReq.setGenChallenge(genChallenge);
-			authorizationReq.setId("authorizationReq");
+			/*
+			 * Experience from the test symposium in San Diego (April 2016):
+			 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+			 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+			 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+			 */
+			authorizationReq.setId("id1");
 		}
 		
 		return authorizationReq;

+ 1 - 1
RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForChargeParameterDiscoveryRes.java

@@ -162,7 +162,7 @@ public class WaitForChargeParameterDiscoveryRes extends ClientState {
 			X509Certificate moSub2Certificate = SecurityUtils.getMOSub2Certificate(
 													GlobalValues.EVCC_KEYSTORE_FILEPATH.toString());
 			if (moSub2Certificate == null) {
-				getLogger().error("No MOSub2Certificate found");
+				getLogger().error("No MOSub2Certificate found, signature of sales tariff could therefore not be verified");
 				return false;
 			} else {
 				ECPublicKey ecPublicKey = (ECPublicKey) moSub2Certificate.getPublicKey();

+ 7 - 1
RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForChargingStatusRes.java

@@ -38,7 +38,13 @@ public class WaitForChargingStatusRes extends ClientState {
 			// ReceiptRequired has higher priority than a possible EVSENotification=Renegotiate
 			if (chargingStatusRes.isReceiptRequired()) {
 				MeteringReceiptReqType meteringReceiptReq = new MeteringReceiptReqType();
-				meteringReceiptReq.setId("meteringReceiptReq");
+				/*
+				 * Experience from the test symposium in San Diego (April 2016):
+				 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+				 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+				 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+				 */
+				meteringReceiptReq.setId("id1");
 				meteringReceiptReq.setMeterInfo(chargingStatusRes.getMeterInfo());
 				meteringReceiptReq.setSAScheduleTupleID(chargingStatusRes.getSAScheduleTupleID());
 				meteringReceiptReq.setSessionID(getCommSessionContext().getSessionID());

+ 7 - 1
RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForCurrentDemandRes.java

@@ -37,7 +37,13 @@ public class WaitForCurrentDemandRes extends ClientState {
 			// ReceiptRequired has higher priority than a possible EVSENotification=Renegotiate
 			if (currentDemandRes.isReceiptRequired()) {
 				MeteringReceiptReqType meteringReceiptReq = new MeteringReceiptReqType();
-				meteringReceiptReq.setId("MeterInfo");
+				/*
+				 * Experience from the test symposium in San Diego (April 2016):
+				 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+				 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+				 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+				 */
+				meteringReceiptReq.setId("id1");
 				meteringReceiptReq.setMeterInfo(currentDemandRes.getMeterInfo());
 				meteringReceiptReq.setSAScheduleTupleID(currentDemandRes.getSAScheduleTupleID());
 				meteringReceiptReq.setSessionID(getCommSessionContext().getSessionID());

+ 1 - 0
RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForPaymentDetailsRes.java

@@ -43,6 +43,7 @@ public class WaitForPaymentDetailsRes extends ClientState {
 			} else {
 				// Set xml reference element
 				AuthorizationReqType authorizationReq = getAuthorizationReq(paymentDetailsRes.getGenChallenge());
+				
 				getXMLSignatureRefElements().put(
 						authorizationReq.getId(), 
 						SecurityUtils.generateDigest(authorizationReq, false));

+ 14 - 2
RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForPaymentServiceSelectionRes.java

@@ -72,7 +72,13 @@ public class WaitForPaymentServiceSelectionRes extends ClientState {
 				GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString());
 		
 		CertificateInstallationReqType certInstallationReq = new CertificateInstallationReqType();
-		certInstallationReq.setId("certificateInstallationReq");
+		/*
+		 * Experience from the test symposium in San Diego (April 2016):
+		 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+		 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+		 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+		 */
+		certInstallationReq.setId("id1");
 		certInstallationReq.setListOfRootCertificateIDs(
 				SecurityUtils.getListOfRootCertificateIDs(
 						GlobalValues.EVCC_TRUSTSTORE_FILEPATH.toString(),
@@ -105,7 +111,13 @@ public class WaitForPaymentServiceSelectionRes extends ClientState {
 								GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString()), 
 						GlobalValues.ALIAS_CONTRACT_CERTIFICATE.toString()));	
 		certificateUpdateReq.setEMAID(SecurityUtils.getEMAID(GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString()).getValue());
-		certificateUpdateReq.setId("certificateUpdateReq");
+		/*
+		 * Experience from the test symposium in San Diego (April 2016):
+		 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+		 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+		 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+		 */
+		certificateUpdateReq.setId("id1");
 		certificateUpdateReq.setListOfRootCertificateIDs(
 				SecurityUtils.getListOfRootCertificateIDs(
 						GlobalValues.EVCC_TRUSTSTORE_FILEPATH.toString(),

+ 7 - 1
RISE-V2G-EVCC/src/main/java/org/eclipse/risev2g/evcc/states/WaitForServiceDiscoveryRes.java

@@ -93,7 +93,8 @@ public class WaitForServiceDiscoveryRes extends ClientState {
 	 * Furthermore, it must be checked if VAS are allowed (-> only if TLS connection is used)
 	 */
 	private boolean useVAS(ServiceDiscoveryResType serviceDiscoveryRes) {
-		if (getCommSessionContext().getTransportLayerClient() instanceof TLSClient) {
+		if (serviceDiscoveryRes.getServiceList() != null && 
+			getCommSessionContext().getTransportLayerClient() instanceof TLSClient) {
 			// Check if certificate service is needed
 			if (isCertificateServiceOffered(serviceDiscoveryRes.getServiceList())) { 
 				getCommSessionContext().setContractCertStatus(SecurityUtils.getContractCertificateStatus());
@@ -128,6 +129,11 @@ public class WaitForServiceDiscoveryRes extends ClientState {
 	
 	
 	private boolean isCertificateServiceOffered(ServiceListType offeredServiceList) {
+		if (offeredServiceList == null) {
+			getLogger().debug("No value added services offered by EVCC");
+			return false;
+		}
+		
 		for (ServiceType service : offeredServiceList.getService()) {
 			if (service.getServiceCategory().equals(ServiceCategoryType.CONTRACT_CERTIFICATE))
 				return true;

+ 24 - 6
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/backend/DummyBackendInterface.java

@@ -20,7 +20,6 @@ import javax.xml.namespace.QName;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.eclipse.risev2g.secc.session.V2GCommunicationSessionSECC;
-import org.eclipse.risev2g.secc.states.ServerState;
 import org.eclipse.risev2g.shared.enumerations.GlobalValues;
 import org.eclipse.risev2g.shared.utils.SecurityUtils;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.CertificateChainType;
@@ -34,6 +33,11 @@ import org.eclipse.risev2g.shared.v2gMessages.msgDef.SalesTariffEntryType;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.SalesTariffType;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.UnitSymbolType;
 
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
 public class DummyBackendInterface implements IBackendInterface {
 
 	private V2GCommunicationSessionSECC commSessionContext;
@@ -97,7 +101,13 @@ public class DummyBackendInterface implements IBackendInterface {
 		 * IMPORTANT: check that you do not add more sales tariff entries than parameter maxEntriesSAScheduleTuple
 		 */
 		SalesTariffType salesTariff = new SalesTariffType();
-		salesTariff.setId("salesTariff");
+		/*
+		 * Experience from the test symposium in San Diego (April 2016):
+		 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+		 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+		 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+		 */
+		salesTariff.setId("id1"); 
 		salesTariff.setSalesTariffID((short) 1);
 		salesTariff.getSalesTariffEntry().add(createSalesTariffEntry(0L, (short) 1));
 		salesTariff.getSalesTariffEntry().add(createSalesTariffEntry(1800L, (short) 4));
@@ -179,12 +189,20 @@ public class DummyBackendInterface implements IBackendInterface {
 	
 	@Override
 	public ECPrivateKey getSAProvisioningCertificatePrivateKey() {
-		KeyStore keyStore = SecurityUtils.getPKCS12KeyStore(
-				"./provServiceCert.p12", 
-				GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString());
-		return SecurityUtils.getPrivateKey(keyStore);
+		Path pathToPrivateKey = FileSystems.getDefault().getPath("./MOSub2_ISO-UG_2016-1_key.bin");
+        byte[] moSub2PrivateKey = null;
+		
+        try {
+			moSub2PrivateKey = Files.readAllBytes(pathToPrivateKey);
+		} catch (IOException e) {
+			getLogger().error("IOException occurred while trying to read MOSub2 private key for signing sales tariff");
+			return null;
+		}
+        
+		return SecurityUtils.getPrivateKey(moSub2PrivateKey);
 	}
 	
+	
 	@Override
 	public CertificateChainType getSAProvisioningCertificateChain() {
 		return SecurityUtils.getCertificateChain("./provServiceCert.p12");

+ 2 - 1
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/evseController/DummyDCEVSEController.java

@@ -20,6 +20,7 @@ import org.eclipse.risev2g.shared.v2gMessages.msgDef.DCEVSEChargeParameterType;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.DCEVSEStatusCodeType;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.DCEVSEStatusType;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.EVSENotificationType;
+import org.eclipse.risev2g.shared.v2gMessages.msgDef.IsolationLevelType;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.MeterInfoType;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.PhysicalValueType;
 import org.eclipse.risev2g.shared.v2gMessages.msgDef.UnitSymbolType;
@@ -87,7 +88,7 @@ public class DummyDCEVSEController implements IDCEVSEController {
 		dcEvseStatus.setNotificationMaxDelay(0);
 		dcEvseStatus.setEVSENotification((notification != null) ? notification : EVSENotificationType.NONE);
 		dcEvseStatus.setEVSEStatusCode(DCEVSEStatusCodeType.EVSE_READY);
-//		dcEvseStatus.setEVSEIsolationStatus(IsolationLevelType.INVALID);
+		dcEvseStatus.setEVSEIsolationStatus(IsolationLevelType.VALID);
 		
 		return dcEvseStatus;
 	}

+ 1 - 1
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/session/V2GCommunicationSessionHandlerSECC.java

@@ -141,7 +141,7 @@ public class V2GCommunicationSessionHandlerSECC implements Observer {
 			 */
 			byte[] seccAddress = (isSecureCommunication()) ? TLSServer.getInstance().getServerAddress().getAddress() : TCPServer.getInstance().getServerAddress().getAddress();
 			int seccPort = (isSecureCommunication()) ? TLSServer.getInstance().getServerPort() : TCPServer.getInstance().getServerPort();
-			
+					
 			SECCDiscoveryRes seccDiscoveryRes = new SECCDiscoveryRes(
 														seccAddress,
 														ByteUtils.toByteArrayFromInt(seccPort, true),

+ 2 - 0
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForAuthorizationReq.java

@@ -76,9 +76,11 @@ public class WaitForAuthorizationReq extends ServerState {
 			// Verify signature
 			HashMap<String, byte[]> verifyXMLSigRefElements = new HashMap<String, byte[]>();
 			verifyXMLSigRefElements.put(authorizationReq.getId(), SecurityUtils.generateDigest(authorizationReq, false));
+			
 			ECPublicKey ecPublicKey = (ECPublicKey) SecurityUtils.getCertificate(
 					getCommSessionContext().getContractSignatureCertChain().getCertificate())
 					.getPublicKey();
+			
 			if (!SecurityUtils.verifySignature(signature, verifyXMLSigRefElements, ecPublicKey)) {
 				authorizationRes.setResponseCode(ResponseCodeType.FAILED_SIGNATURE_ERROR);
 				return false;

+ 10 - 4
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForCertificateInstallationReq.java

@@ -61,13 +61,19 @@ public class WaitForCertificateInstallationReq extends ServerState  {
 								getCommSessionContext().getBackendInterface().getContractCertificatePrivateKey());
 				
 				certificateInstallationRes.setContractSignatureCertChain(saContractCertificateChain);
-				certificateInstallationRes.getContractSignatureCertChain().setId("contractSignatureCertChain");
+				/*
+				 * Experience from the test symposium in San Diego (April 2016):
+				 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+				 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+				 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+				 */
+				certificateInstallationRes.getContractSignatureCertChain().setId("id1"); // contractSignatureCertChain
 				certificateInstallationRes.setContractSignatureEncryptedPrivateKey(encryptedContractCertPrivateKey);
-				certificateInstallationRes.getContractSignatureEncryptedPrivateKey().setId("contractSignatureEncryptedPrivateKey");
+				certificateInstallationRes.getContractSignatureEncryptedPrivateKey().setId("id2"); // contractSignatureEncryptedPrivateKey
 				certificateInstallationRes.setDHpublickey(SecurityUtils.getDHPublicKey(ecdhKeyPair));
-				certificateInstallationRes.getDHpublickey().setId("dhPublicKey");
+				certificateInstallationRes.getDHpublickey().setId("id3"); // dhPublicKey
 				certificateInstallationRes.setEMAID(SecurityUtils.getEMAID(saContractCertificateChain));
-				certificateInstallationRes.getEMAID().setId("emaid");
+				certificateInstallationRes.getEMAID().setId("id4"); // emaid
 				certificateInstallationRes.setSAProvisioningCertificateChain(
 						getCommSessionContext().getBackendInterface().getSAProvisioningCertificateChain());
 				

+ 10 - 4
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForCertificateUpdateReq.java

@@ -63,13 +63,19 @@ public class WaitForCertificateUpdateReq extends ServerState  {
 								getCommSessionContext().getBackendInterface().getContractCertificatePrivateKey());
 				
 				certificateUpdateRes.setContractSignatureCertChain(contractCertificateChain);
-				certificateUpdateRes.getContractSignatureCertChain().setId("contractSignatureCertChain");
+				/*
+				 * Experience from the test symposium in San Diego (April 2016):
+				 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+				 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+				 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+				 */
+				certificateUpdateRes.getContractSignatureCertChain().setId("id1"); // contractSignatureCertChain
 				certificateUpdateRes.setContractSignatureEncryptedPrivateKey(encryptedContractCertPrivateKey);
-				certificateUpdateRes.getContractSignatureEncryptedPrivateKey().setId("contractSignatureEncryptedPrivateKey");
+				certificateUpdateRes.getContractSignatureEncryptedPrivateKey().setId("id2"); // contractSignatureEncryptedPrivateKey
 				certificateUpdateRes.setDHpublickey(SecurityUtils.getDHPublicKey(ecdhKeyPair));
-				certificateUpdateRes.getDHpublickey().setId("dhPublicKey");
+				certificateUpdateRes.getDHpublickey().setId("id3"); // dhPublicKey
 				certificateUpdateRes.setEMAID(SecurityUtils.getEMAID(contractCertificateChain));
-				certificateUpdateRes.getEMAID().setId("emaid");
+				certificateUpdateRes.getEMAID().setId("id4"); // emaid
 				certificateUpdateRes.setSAProvisioningCertificateChain(getCommSessionContext().getBackendInterface().getSAProvisioningCertificateChain());
 				
 				// In case of negative response code, try at next charging (retryCounter = 0)

+ 3 - 0
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForPaymentServiceSelectionReq.java

@@ -37,6 +37,9 @@ public class WaitForPaymentServiceSelectionReq extends ServerState {
 			PaymentServiceSelectionReqType paymentServiceSelectionReq = 
 					(PaymentServiceSelectionReqType) v2gMessageReq.getBody().getBodyElement().getValue();
 			
+			getLogger().info("Payment option " + paymentServiceSelectionReq.getSelectedPaymentOption().toString() + 
+							 " has been chosen by EVCC");
+			
 			if (isResponseCodeOK(paymentServiceSelectionReq)) {
 				// see [V2G2-551]
 				if (paymentServiceSelectionReq.getSelectedPaymentOption().equals(PaymentOptionType.CONTRACT)) {

+ 13 - 2
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForServiceDiscoveryReq.java

@@ -78,8 +78,19 @@ public class WaitForServiceDiscoveryReq extends ServerState {
 		chargeService.setSupportedEnergyTransferMode(supportedEnergyTransferModes);
 		chargeService.setServiceCategory(ServiceCategoryType.EV_CHARGING);
 		chargeService.setServiceID(1); // according to Table 105 ISO/IEC 15118-2
-		chargeService.setServiceName("EV charging (AC/DC)"); // optional value
-		chargeService.setServiceScope("");  // optional value
+		
+		/*
+		 * Is an optional value, but fill it with a non-empty string if used, 
+		 * otherwise an EXI decoding error could occur on the other side!
+		 */
+		chargeService.setServiceName("EV charging (AC/DC)"); 
+		
+		/*
+		 * Is an optional value, but fill it with a non-empty string if used, 
+		 * otherwise an EXI decoding error could occur on the other side!
+		 */
+//		chargeService.setServiceScope("");
+		
 		chargeService.setFreeService(false); // it is supposed that charging is by default not for free
 		
 		return chargeService;

+ 9 - 1
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/states/WaitForSupportedAppProtocolReq.java

@@ -77,10 +77,18 @@ public class WaitForSupportedAppProtocolReq extends ServerState {
 		} else if (message instanceof SECCDiscoveryReq) {
 			getLogger().debug("Another SECCDiscoveryReq was received, changing to state WaitForSECCDiscoveryReq");
 			return new ChangeProcessingState(message, getCommSessionContext().getStates().get(V2GMessages.SECC_DISCOVERY_REQ));
-		} else {
+		} else if (message != null) {
+			/*
+			 * This check has been introduced to make sure the application can deal with incoming messages which rely 
+			 * on the DINSPEC 70121 XSD schema (which is different from the ISO 15118-2 schema. Without this check, 
+			 * the message.getClass() would throw a NullPointerException and the application would die.
+			 */
 			getLogger().error("Invalid message (" + message.getClass().getSimpleName() + 
 							  ") at this state (" + this.getClass().getSimpleName() + ")");
 			supportedAppProtocolRes.setResponseCode(ResponseCodeType.FAILED_NO_NEGOTIATION);
+		} else {
+			getLogger().error("Invalid message at this state, message seems to be null. Check if same XSD schema is used on EVCC side.");
+			supportedAppProtocolRes.setResponseCode(ResponseCodeType.FAILED_NO_NEGOTIATION);
 		}
 		
 		return getSendMessage(supportedAppProtocolRes, 

+ 1 - 1
RISE-V2G-Shared/src/main/java/org/eclipse/risev2g/shared/utils/MiscUtils.java

@@ -264,7 +264,7 @@ public final class MiscUtils {
 	 * (I don't know how to infer the type correctly)
 	 * 
 	 * @param messageOrField The message or field for which a digest is to be generated
-	 * @return
+	 * @return The JAXBElement of the provided message or field
 	 */
 	@SuppressWarnings({ "rawtypes", "unchecked" })
 	public static JAXBElement getJaxbElement(Object messageOrField) {

+ 22 - 5
RISE-V2G-Shared/src/main/java/org/eclipse/risev2g/shared/utils/SecurityUtils.java

@@ -600,7 +600,13 @@ public final class SecurityUtils {
 	 */
 	public static DiffieHellmanPublickeyType getDHPublicKey(KeyPair ecdhKeyPair) {
 		DiffieHellmanPublickeyType dhPublicKey = new DiffieHellmanPublickeyType();
-		dhPublicKey.setId("dhPublicKey"); 
+		/*
+		 * Experience from the test symposium in San Diego (April 2016):
+		 * The Id element of the signature is not restricted in size by the standard itself. But on embedded 
+		 * systems, the memory is very limited which is why we should not use long IDs for the signature reference
+		 * element. A good size would be 3 characters max (like the example in the ISO 15118-2 annex J)
+		 */
+		dhPublicKey.setId("id1"); // dhPublicKey
 		dhPublicKey.setValue(ecdhKeyPair.getPublic().getEncoded());
 		
 		return dhPublicKey;
@@ -1537,7 +1543,7 @@ public final class SecurityUtils {
 				SignatureType signature, 
 				HashMap<String, byte[]> verifyXMLSigRefElements, 
 				ECPublicKey ecPublicKey) {
-		byte[] providedDigest; 
+		byte[] calculatedReferenceDigest; 
 		boolean match;
 		
 		/*
@@ -1548,17 +1554,28 @@ public final class SecurityUtils {
 		for (String id : verifyXMLSigRefElements.keySet()) {
 			getLogger().debug("Verifying digest for element '" + id + "'");
 			match = false;
-			providedDigest = verifyXMLSigRefElements.get(id);
+			calculatedReferenceDigest = verifyXMLSigRefElements.get(id);
 			
 			// A bit inefficient, but there are max. 4 elements to iterate over (what would be more efficient?)
 			for (ReferenceType reference : signature.getSignedInfo().getReference()) {
-				if (reference.getId().equals(id) && Arrays.equals(reference.getDigestValue(), providedDigest))
+				if (reference == null) {
+					getLogger().warn("Reference element to check is null");
+					continue;
+				}
+				
+				// We need to check the URI attribute, the Id attribute is likely to be null
+				if (reference.getURI() == null) {
+					getLogger().warn("Reference ID element is null");
+					continue;
+				}
+				
+				if (reference.getURI().equals('#' + id) && Arrays.equals(reference.getDigestValue(), calculatedReferenceDigest))
 					match = true;
 			}
 			
 			if (!match) {
 				getLogger().error("No matching signature found for ID '" + id + "' and digest value " + 
-								  ByteUtils.toHexString(providedDigest));
+								  ByteUtils.toHexString(calculatedReferenceDigest));
 				return false;
 			}
 		}