Kaynağa Gözat

- Bugfix: The signature key for signing SalesTariff elements was wrong (not the provisioning service certificate private key but the MO Sub-CA 2 certificate private key needs to be used here).
- Modified DummyBackendInterface and IBackendInterface to introduce method getMOSubCA2CertificatePrivateKey()
- New function in SecurityUtils introduced to read .key private key file.
- Added warning logger message on SECC side in case the SAScheduleTupleID in PowerDeliveryReq message is null (parameter is mandatory, although setting it is actually useless when PowerDeliveryReq with ChargeProgress set to 'Stop' is set).

Marc Mültin 9 yıl önce
ebeveyn
işleme
03fe9c4ee8

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

@@ -205,6 +205,18 @@ public class DummyBackendInterface implements IBackendInterface {
 		return privateKey;
 	}
 	
+	@Override
+	public ECPrivateKey getMOSubCA2CertificatePrivateKey() {
+		ECPrivateKey privateKey = SecurityUtils.getPrivateKey(
+				"./PKI-1_CRT_MO_SUB2_VALID.key", 
+				GlobalValues.PASSPHRASE_FOR_CERTIFICATES_AND_KEYS.toString());
+		
+		if (privateKey == null) 
+			getLogger().error("No private key available from MO Sub-CA 2 PKCS#8 file");
+		
+		return privateKey;
+	}
+	
 	
 	@Override
 	public CertificateChainType getSAProvisioningCertificateChain() {

+ 7 - 0
RISE-V2G-SECC/src/main/java/org/eclipse/risev2g/secc/backend/IBackendInterface.java

@@ -57,4 +57,11 @@ public interface IBackendInterface {
 	 * @return PrivateKey of the SA provisioning certificate
 	 */
 	public ECPrivateKey getSAProvisioningCertificatePrivateKey();
+	
+	
+	/**
+	 * Provides the private key belonging to the MO Sub-CA 2 certificate (signature of SalesTariff).
+	 * @return PrivateKey of the MO Sub-CA 2 certificate
+	 */
+	public ECPrivateKey getMOSubCA2CertificatePrivateKey();
 }

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

@@ -106,8 +106,8 @@ public class WaitForChargeParameterDiscoveryReq extends ServerState {
 					chargeParameterDiscoveryRes.setSASchedules(
 							getSASchedulesAsJAXBElement(getCommSessionContext().getSaSchedules()));
 					
-					// Set signing private key
-					setSignaturePrivateKey(getCommSessionContext().getBackendInterface().getSAProvisioningCertificatePrivateKey());
+					// Set signing private key of Mobility Operator Sub-CA 2
+					setSignaturePrivateKey(getCommSessionContext().getBackendInterface().getMOSubCA2CertificatePrivateKey());
 					
 					if (chargeParameterDiscoveryReq.getRequestedEnergyTransferMode().toString().startsWith("AC")) 
 						return getSendMessage(chargeParameterDiscoveryRes, V2GMessages.POWER_DELIVERY_REQ);

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

@@ -110,6 +110,7 @@ public class WaitForPowerDeliveryReq extends ServerState {
 		SAScheduleTupleType chosenSASchedule = getChosenSASCheduleTuple(powerDeliveryReq.getSAScheduleTupleID());
 		
 		if (chosenSASchedule == null) {
+			getLogger().warn("Chosen SAScheduleTupleID in PowerDeliveryReq is null, but parameter is mandatory");
 			powerDeliveryRes.setResponseCode(ResponseCodeType.FAILED_TARIFF_SELECTION_INVALID);
 			return false;
 		}

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

@@ -12,6 +12,7 @@ package org.eclipse.risev2g.shared.utils;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -30,7 +31,6 @@ import java.security.KeyStoreException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
-import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.Signature;
@@ -645,13 +645,13 @@ public final class SecurityUtils {
 	 * contract certificate, its private key and an optional chain of intermediate CAs.
 	 * 
 	 * @param keyStore The PKCS#12 keystore provided by the secondary actor
-	 * @return The private key contained in the given keystore
+	 * @return The private key contained in the given keystore as an ECPrivateKey
 	 */
 	public static ECPrivateKey getPrivateKey(KeyStore keyStore) {
 		/*
 		 * For testing purposes, the respective PKCS12 container file chain has already been put in the 
 		 * resources folder. However, when implementing a real interface to a secondary actor's backend, 
-		 * the retrieval of a PKCS12 container file must be done via some other online mechanism.
+		 * the retrieval of a PKCS#12 container file must be done via some other online mechanism.
 		 */
 		
 		ECPrivateKey privateKey = null;
@@ -674,6 +674,34 @@ public final class SecurityUtils {
 	}
 	
 	
+	/**
+	 * Read a private key from a .key file and return it as an ECPrivateKey
+	 * 
+	 * @param A .key file containing the private key
+	 * @return The private key stored in the .key file as an ECPrivateKey
+	 */
+	public static ECPrivateKey getPrivateKey(String keyFilePath, String password) {
+		File file = null;
+		FileInputStream fis = null;
+		
+		try {
+			file = new File(keyFilePath);
+			fis = new FileInputStream(file);
+			byte[] privateKeyByteArray = new byte[(int) file.length()];
+			
+			ECPrivateKey privateKey = getPrivateKey(privateKeyByteArray);
+
+			fis.close();
+			
+			return privateKey;
+		} catch (NullPointerException | IOException e) {
+			getLogger().error(e.getClass().getSimpleName() + " occurred while trying to access private key at " +
+							  "location '" + keyFilePath + "'");
+			return null;
+		}
+	}
+	
+	
 	/**
 	 * Searches the given keystore for the private key which corresponds to the provided alias.
 	 * Example: In case of the EVCC and during certificate installation, the private key of the