Procházet zdrojové kódy

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 před 10 roky
rodič
revize
6345846e7b
20 změnil soubory, kde provedl 148 přidání a 37 odebrání
  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;
 			}
 		}