Эх сурвалжийг харах

2022-08-30/Jerry Wang
[OCPP 1.6]
Action:
1. Add the logic that check 'CustomIdleFeeAfterStop' key to determine if charger should send 'connectorUnplugged' dms message or not.
2. Add and modify certificate related functions for high level security profile. (Under testing)
3. Correct the parameter 'ItemAccessibility' of AuthorizeRemoteTxRequests key to 1.
4. Modify the delay time in SignedUpdateFirmwareProcess() function.

File:
1. EVSE/Modularization/ocppfiles/MessageHandler.c
--> Action 1-4

Jerry Wang 2 жил өмнө
parent
commit
0ef482fed1

+ 549 - 40
EVSE/Modularization/ocppfiles/MessageHandler.c

@@ -5144,7 +5144,7 @@ void CheckSystemValue(void)
 					if((ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].SystemStatus != ChademoPreviousSystemStatus[index]) || (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].ConnectorPlugIn != ChademoPreviousConnectorPlugIn[index]) )
 					{
 						// Sent unplug message for California pricing logic
-						if((ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].ConnectorPlugIn == 0) && !interLock.isSentUnplug[gun_index])
+						if((strcmp((const char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[CustomIdleFeeAfterStop].ItemData, "TRUE") == 0) && (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].ConnectorPlugIn == 0) && !interLock.isSentUnplug[gun_index])
 						{
 							uint8_t ts[36];
 							getNowDatetime(ts);
@@ -5210,7 +5210,7 @@ void CheckSystemValue(void)
 					if((ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].SystemStatus != CcsPreviousSystemStatus[index]) || (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].ConnectorPlugIn != CcsPreviousConnectorPlugIn[index]) )//if(ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].SystemStatus != CcsPreviousSystemStatus[index]/*PRE_SYS_MODE[gun_index]*/ )
 					{
 						// Sent unplug message for California pricing logic
-						if((ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].ConnectorPlugIn == 0) && !interLock.isSentUnplug[gun_index])
+						if((strcmp((const char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[CustomIdleFeeAfterStop].ItemData, "TRUE") == 0) && (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].ConnectorPlugIn == 0) && !interLock.isSentUnplug[gun_index])
 						{
 							uint8_t ts[36];
 							getNowDatetime(ts);
@@ -5276,7 +5276,7 @@ void CheckSystemValue(void)
 					if((ShmSysConfigAndInfo->SysInfo.GbChargingData[index].SystemStatus != GbPreviousSystemStatus[index]) || (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].ConnectorPlugIn != GbPreviousConnectorPlugIn[index]) )
 					{
 						// Sent unplug message for California pricing logic
-						if((ShmSysConfigAndInfo->SysInfo.GbChargingData[index].SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].ConnectorPlugIn == 0) && !interLock.isSentUnplug[gun_index])
+						if((strcmp((const char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[CustomIdleFeeAfterStop].ItemData, "TRUE") == 0) && (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].ConnectorPlugIn == 0) && !interLock.isSentUnplug[gun_index])
 						{
 							uint8_t ts[36];
 							getNowDatetime(ts);
@@ -5334,7 +5334,7 @@ void CheckSystemValue(void)
 					if((ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].GeneralChargingData.SystemStatus != DoPreviousSystemStatus[index]) || (ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].GeneralChargingData.ConnectorPlugIn != DoPreviousConnectorPlugIn[index]) )
 					{
 						// Sent unplug message for California pricing logic
-						if((ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].GeneralChargingData.SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].GeneralChargingData.ConnectorPlugIn == 0) && !interLock.isSentUnplug[gun_index])
+						if((strcmp((const char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[CustomIdleFeeAfterStop].ItemData, "TRUE") == 0) && (ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].GeneralChargingData.SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.ConnectorInfo[index].GeneralChargingData.ConnectorPlugIn == 0) && !interLock.isSentUnplug[gun_index])
 						{
 							uint8_t ts[36];
 							getNowDatetime(ts);
@@ -5399,7 +5399,7 @@ void CheckSystemValue(void)
 					if((ShmSysConfigAndInfo->SysInfo.AcChargingData[index].SystemStatus != AcPreviousSystemStatus[index]) || (ShmSysConfigAndInfo->SysInfo.AcChargingData[index].PilotState != AcPreviousConnectorPlugIn[index]) )
 					{
 						// Sent unplug message for California pricing logic
-						if((ShmSysConfigAndInfo->SysInfo.AcChargingData[index].SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.AcChargingData[index].PilotState == CP_STATE_A) && !interLock.isSentUnplug[gun_index])
+						if((strcmp((const char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[CustomIdleFeeAfterStop].ItemData, "TRUE") == 0) && (ShmSysConfigAndInfo->SysInfo.AcChargingData[index].SystemStatus == SYS_MODE_COMPLETE) && (ShmSysConfigAndInfo->SysInfo.AcChargingData[index].PilotState == CP_STATE_A) && !interLock.isSentUnplug[gun_index])
 						{
 							uint8_t ts[36];
 							getNowDatetime(ts);
@@ -9488,14 +9488,17 @@ int sendGetInstalledCertificateIdsConfirmation(char *uuid)
 	{
 		for(int idx=0;idx<ARRAY_SIZE(ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData);idx++)
 		{
-			json_object *certificateHashData = json_object_new_object();
+			if(strlen((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].hashAlgorithm) > 0)
+			{
+				json_object *certificateHashData = json_object_new_object();
 
-			json_object_object_add(certificateHashData, "hashAlgorithm", json_object_new_string((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].hashAlgorithm));
-			json_object_object_add(certificateHashData, "issuerNameHash", json_object_new_string((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].issuerNameHash));
-			json_object_object_add(certificateHashData, "issuerKeyHash", json_object_new_string((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].issuerKeyHash));
-			json_object_object_add(certificateHashData, "serialNumber", json_object_new_string((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].serialNumber));
+				json_object_object_add(certificateHashData, "hashAlgorithm", json_object_new_string((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].hashAlgorithm));
+				json_object_object_add(certificateHashData, "issuerNameHash", json_object_new_string((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].issuerNameHash));
+				json_object_object_add(certificateHashData, "issuerKeyHash", json_object_new_string((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].issuerKeyHash));
+				json_object_object_add(certificateHashData, "serialNumber", json_object_new_string((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[idx].serialNumber));
 
-			json_object_array_add(certificateHashDataDatas, certificateHashData);
+				json_object_array_add(certificateHashDataDatas, certificateHashData);
+			}
 		}
 		json_object_object_add(GetInstalledCertificateIds , "certificateHashData", certificateHashDataDatas);
 	}
@@ -15371,6 +15374,7 @@ int handleDeleteCertificateRequest(char *uuid, char *payload)
 	json_object *DeleteCertificate;
 
 	DEBUG_INFO("handleDeleteCertificateRequest...\n");
+	sprintf((char*)ShmOCPP16Data->DeleteCertificate.Response_status, "NotFound");
 	DeleteCertificate = json_tokener_parse(payload);
 	if(!is_error(DeleteCertificate))
 	{
@@ -15378,19 +15382,204 @@ int handleDeleteCertificateRequest(char *uuid, char *payload)
 		sprintf((char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerNameHash, "%s", json_object_get_string(json_object_object_get(json_object_object_get(DeleteCertificate, "certificateHashData"), "issuerNameHash")));
 		sprintf((char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash, "%s", json_object_get_string(json_object_object_get(json_object_object_get(DeleteCertificate, "certificateHashData"), "issuerKeyHash")));
 		sprintf((char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber, "%s", json_object_get_string(json_object_object_get(json_object_object_get(DeleteCertificate, "certificateHashData"), "serialNumber")));
+
+		DEBUG_INFO("hashAlgorithm: %s\n", ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
+		DEBUG_INFO("issuerNameHash: %s\n", ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerNameHash);
+		DEBUG_INFO("issuerKeyHash: %s\n", ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash);
+		DEBUG_INFO("serialNumber: %s\n", ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber);
+
+		char temp[256] = {0};
+		char compareData[256] = {0};
+		int  isMatch = TRUE;
+
+		FILE *fp;
+		if(access("/Storage/OCPP/CentralSystemRootCertificate.pem",F_OK) != -1)
+		{
+			// Check CentralSystemRootCertificate
+			DEBUG_INFO("Checking CentralSystemRootCertificate...\n");
+			sprintf(temp ,"openssl x509 -noout -serial -in /Storage/OCPP/CentralSystemRootCertificate.pem");
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "serial=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", compareData);
+						break;
+					}
+				}
+				DEBUG_INFO("SerialNumber= %s...\n", compareData);
+			}
+			if(strcmp(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) != 0)
+				isMatch = FALSE;
+
+			if(isMatch == TRUE)
+			{
+				memset(compareData, 0, ARRAY_SIZE(compareData));
+				sprintf(temp ,"openssl x509 -noout -issuer -in /Storage/OCPP/CentralSystemRootCertificate.pem | openssl dgst -%s", (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
+				fp = popen(temp, "r");
+				if(fp)
+				{
+					while(fgets(temp, sizeof(temp), fp) != NULL)
+					{
+						strcat(compareData, temp);
+					}
+				}
+				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) == NULL)
+					isMatch = FALSE;
+			}
+
+			if(isMatch == TRUE)
+			{
+				memset(compareData, 0, ARRAY_SIZE(compareData));
+				sprintf(temp ,"openssl x509 -noout -pubkey -in /Storage/OCPP/CentralSystemRootCertificate.pem | openssl dgst -%s", (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
+				fp = popen(temp, "r");
+				if(fp)
+				{
+					while(fgets(temp, sizeof(temp), fp) != NULL)
+					{
+						strcat(compareData, temp);
+					}
+				}
+				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash) == NULL)
+					isMatch = FALSE;
+			}
+
+			if(isMatch == TRUE)
+			{
+				system("rm -f /Storage/OCPP/CentralSystemRootCertificate.pem");
+				sprintf((char*)ShmOCPP16Data->DeleteCertificate.Response_status, "Accepted");
+				goto End;
+			}
+		}
+
+		// Check ManufacturerRootCertificate
+		if(access("/Storage/OCPP/ManufacturerRootCertificate.pem",F_OK) != -1)
+		{
+			isMatch = FALSE;
+			sprintf(temp ,"openssl x509 -noout -serial -in /Storage/OCPP/ManufacturerRootCertificate.pem");
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "serial=") != NULL)
+					{
+						DEBUG_INFO("Certificate enddate info: %s\n", temp);
+						sscanf(temp, "%*[^=]=%s", compareData);
+						break;
+					}
+				}
+			}
+			if(strcmp(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) != 0)
+				isMatch = FALSE;
+
+			if(isMatch == TRUE)
+			{
+				memset(compareData, 0, ARRAY_SIZE(compareData));
+				sprintf(temp ,"openssl x509 -noout -issuer -in /Storage/OCPP/ManufacturerRootCertificate.pem | openssl dgst -%s", (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
+				fp = popen(temp, "r");
+				if(fp)
+				{
+					while(fgets(temp, sizeof(temp), fp) != NULL)
+					{
+						strcat(compareData, temp);
+					}
+				}
+				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) == NULL)
+					isMatch = FALSE;
+			}
+
+			if(isMatch == TRUE)
+			{
+				memset(compareData, 0, ARRAY_SIZE(compareData));
+				sprintf(temp ,"openssl x509 -noout -pubkey -in /Storage/OCPP/ManufacturerRootCertificate.pem | openssl dgst -%s", (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
+				fp = popen(temp, "r");
+				if(fp)
+				{
+					while(fgets(temp, sizeof(temp), fp) != NULL)
+					{
+						strcat(compareData, temp);
+					}
+				}
+				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash) == NULL)
+					isMatch = FALSE;
+			}
+
+			if(isMatch == TRUE)
+			{
+				system("rm -f /Storage/OCPP/ManufacturerRootCertificate.pem");
+				sprintf((char*)ShmOCPP16Data->DeleteCertificate.Response_status, "Accepted");
+				goto End;
+			}
+		}
+
+		// Check certCP
+		if(access("/Storage/OCPP/certCP.pem",F_OK) != -1)
+		{
+			isMatch = FALSE;
+			sprintf(temp ,"openssl x509 -noout -serial -in /Storage/OCPP/certCP.pem");
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "serial=") != NULL)
+					{
+						DEBUG_INFO("Certificate enddate info: %s\n", temp);
+						sscanf(temp, "%*[^=]=%s", compareData);
+						break;
+					}
+				}
+			}
+			if(strcmp(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) != 0)
+				isMatch = FALSE;
+
+			if(isMatch == TRUE)
+			{
+				memset(compareData, 0, ARRAY_SIZE(compareData));
+				sprintf(temp ,"openssl x509 -noout -issuer -in /Storage/OCPP/certCP.pem | openssl dgst -%s", (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
+				fp = popen(temp, "r");
+				if(fp)
+				{
+					while(fgets(temp, sizeof(temp), fp) != NULL)
+					{
+						strcat(compareData, temp);
+					}
+				}
+				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) == NULL)
+					isMatch = FALSE;
+			}
+
+			if(isMatch == TRUE)
+			{
+				memset(compareData, 0, ARRAY_SIZE(compareData));
+				sprintf(temp ,"openssl x509 -noout -pubkey -in /Storage/OCPP/certCP.pem | openssl dgst -%s", (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
+				fp = popen(temp, "r");
+				if(fp)
+				{
+					while(fgets(temp, sizeof(temp), fp) != NULL)
+					{
+						strcat(compareData, temp);
+					}
+				}
+				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash) == NULL)
+					isMatch = FALSE;
+			}
+
+			if(isMatch == TRUE)
+			{
+				system("rm -f /Storage/OCPP/certCP.pem");
+				sprintf((char*)ShmOCPP16Data->DeleteCertificate.Response_status, "Accepted");
+				goto End;
+			}
+		}
 	}
-	json_object_put(DeleteCertificate);
 
-	/*
-	 *	TODO: Delete certificateSigned process
-	 */
+End:
+	json_object_put(DeleteCertificate);
 	ShmOCPP16Data->MsMsg.bits.DeleteCertificateReq = 1;
-	DEBUG_INFO("hashAlgorithm: %s\n", ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
-	DEBUG_INFO("issuerNameHash: %s\n", ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerNameHash);
-	DEBUG_INFO("issuerKeyHash: %s\n", ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash);
-	DEBUG_INFO("serialNumber: %s\n", ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber);
-
-	sprintf((char*)ShmOCPP16Data->DeleteCertificate.Response_status, "NotFound");
 	sendDeleteCertificateConfirmation(uuid);
 
 	return result;
@@ -15523,20 +15712,192 @@ int handleGetInstalledCertificateIdsRequest(char *uuid, char *payload)
 
 	DEBUG_INFO("handleGetInstalledCertificateIdsRequest...\n");
 	GetInstalledCertificateIds = json_tokener_parse(payload);
+	memset(ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData, 0x00, ARRAY_SIZE(ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData)*sizeof(struct CertificateHashDataType));
+
 	if(!is_error(GetInstalledCertificateIds))
 	{
 		sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.certificateType, "%s", json_object_get_string(json_object_object_get(GetInstalledCertificateIds, "certificateType")));
+		DEBUG_INFO("Requested Certificate: %s\n", (char*)ShmOCPP16Data->GetInstalledCertificateIds.certificateType);
+		sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_status, "Accepted");
+
+		char temp[512] = {0};
+		char capturedData[256] = {0};
+		char hashType[10] = {0};
+		FILE *fp;
+
+		// Check CentralSystemRootCertificate
+		if((strstr((char*)ShmOCPP16Data->GetInstalledCertificateIds.certificateType, "CentralSystemRootCertificate")!= NULL) && (access("/Storage/OCPP/CentralSystemRootCertificate.pem",F_OK) != -1))
+		{
+			memset(hashType, 0, ARRAY_SIZE(hashType));
+			sprintf(temp ,"openssl x509 -noout -text -in /Storage/OCPP/CentralSystemRootCertificate.pem");
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "Signature Algorithm:") != NULL)
+					{
+						if(strstr(temp, "sha256") != NULL)
+							sprintf((char*)hashType, "SHA256");
+						if(strstr(temp, "sha384") != NULL)
+							sprintf((char*)hashType, "SHA384");
+						if(strstr(temp, "sha512") != NULL)
+							sprintf((char*)hashType, "SHA512");
+
+						break;
+					}
+				}
+				DEBUG_INFO("hashAlgorithm: %s\n", hashType);
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].hashAlgorithm, hashType);
+			}
+
+			memset(capturedData, 0, ARRAY_SIZE(capturedData));
+			sprintf(temp ,"openssl x509 -noout -serial -in /Storage/OCPP/CentralSystemRootCertificate.pem");
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "serial=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						break;
+					}
+				}
+				DEBUG_INFO("serialNumber: %s\n", capturedData);
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].serialNumber, capturedData);
+			}
+
+			memset(capturedData, 0, ARRAY_SIZE(capturedData));
+			sprintf(temp ,"openssl x509 -noout -issuer -in /Storage/OCPP/CentralSystemRootCertificate.pem | openssl dgst -%s", (char*)hashType);
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "(stdin)=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						break;
+					}
+				}
+				stringtrimspace(capturedData);
+				DEBUG_INFO("issuerNameHash: %s\n", capturedData);
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerNameHash, capturedData);
+			}
+
+			memset(capturedData, 0, ARRAY_SIZE(capturedData));
+			sprintf(temp ,"openssl x509 -noout -pubkey -in /Storage/OCPP/CentralSystemRootCertificate.pem | openssl dgst -%s", (char*)hashType);
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "(stdin)=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						break;
+					}
+				}
+				stringtrimspace(capturedData);
+				DEBUG_INFO("issuerKeyHash: %s\n", capturedData);
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerKeyHash, capturedData);
+			}
+		}
+		else
+		{
+			DEBUG_INFO(">>> No CentralSystemRootCertificate found.\n");
+			sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_status, "NotFound");
+		}
+
+		// Check ManufacturerRootCertificate
+		if((strstr((char*)ShmOCPP16Data->GetInstalledCertificateIds.certificateType, "ManufacturerRootCertificate") != NULL) && (access("/Storage/OCPP/ManufacturerRootCertificate.pem",F_OK) != -1))
+		{
+			memset(hashType, 0, ARRAY_SIZE(hashType));
+			sprintf(temp ,"openssl x509 -noout -text -in /Storage/OCPP/ManufacturerRootCertificate.pem");
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "Signature Algorithm:") != NULL)
+					{
+						if(strstr(temp, "sha256") != NULL)
+							sprintf((char*)hashType, "SHA256");
+						if(strstr(temp, "sha384") != NULL)
+							sprintf((char*)hashType, "SHA384");
+						if(strstr(temp, "sha512") != NULL)
+							sprintf((char*)hashType, "SHA512");
+
+						break;
+					}
+				}
+				DEBUG_INFO("hashAlgorithm: %s\n", hashType);
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].hashAlgorithm, hashType);
+			}
+
+			memset(capturedData, 0, ARRAY_SIZE(capturedData));
+			sprintf(temp ,"openssl x509 -noout -serial -in /Storage/OCPP/ManufacturerRootCertificate.pem");
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "serial=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						break;
+					}
+				}
+				DEBUG_INFO("serialNumber: %s\n", capturedData);
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].serialNumber, capturedData);
+			}
+
+			memset(capturedData, 0, ARRAY_SIZE(capturedData));
+			sprintf(temp ,"openssl x509 -noout -issuer -in /Storage/OCPP/ManufacturerRootCertificate.pem | openssl dgst -%s", (char*)hashType);
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "(stdin)=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						break;
+					}
+				}
+				stringtrimspace(capturedData);
+				DEBUG_INFO("issuerNameHash: %s\n", capturedData);
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerNameHash, capturedData);
+			}
+
+			memset(capturedData, 0, ARRAY_SIZE(capturedData));
+			sprintf(temp ,"openssl x509 -noout -pubkey -in /Storage/OCPP/ManufacturerRootCertificate.pem | openssl dgst -%s", (char*)hashType);
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "(stdin)=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						break;
+					}
+				}
+				stringtrimspace(capturedData);
+				DEBUG_INFO("issuerKeyHash: %s\n", capturedData);
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerKeyHash, capturedData);
+			}
+		}
+		else
+		{
+			DEBUG_INFO(">>> No ManufacturerRootCertificate found.\n");
+			sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_status, "NotFound");
+		}
 	}
 	json_object_put(GetInstalledCertificateIds);
 
-	/*
-	 *	TODO: Return installed certificate process
-	 */
 	ShmOCPP16Data->MsMsg.bits.GetInstalledCertificateIdsReq = 1;
-	DEBUG_INFO("requestedMessage: %s\n", (char*)ShmOCPP16Data->GetInstalledCertificateIds.certificateType);
-
-	memset(ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData, 0x00, ARRAY_SIZE(ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData)*sizeof(struct CertificateHashDataType));
-	sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_status, "NotFound");
 	sendGetInstalledCertificateIdsConfirmation(uuid);
 
 	return result;
@@ -15854,6 +16215,7 @@ int handleInstallCertificateRequest(char *uuid, char *payload)
 	mtrace();
 	int result = PASS;
 	json_object *InstallCertificate;
+	sprintf((char*)ShmOCPP16Data->InstallCertificate.Response_status, "Rejected");
 
 	DEBUG_INFO("handleInstallCertificateRequest...\n");
 	InstallCertificate = json_tokener_parse(payload);
@@ -15861,17 +16223,155 @@ int handleInstallCertificateRequest(char *uuid, char *payload)
 	{
 		sprintf((char*)ShmOCPP16Data->InstallCertificate.certificateType, "%s", json_object_get_string(json_object_object_get(InstallCertificate, "certificateType")));
 		sprintf((char*)ShmOCPP16Data->InstallCertificate.certificate, "%s", json_object_get_string(json_object_object_get(InstallCertificate, "certificate")));
+		DEBUG_INFO("certificateType: %s\n", (char*)ShmOCPP16Data->InstallCertificate.certificateType);
+		DEBUG_INFO("certificate: %s\n", (char*)ShmOCPP16Data->InstallCertificate.certificate);
+
+		char tempCert[] = "/Storage/OCPP/tempInstallCertificate.pem";
+		//char filename[128]={0};
+		//char sysCmd[256]={0};
+		char temp[1024];
+
+		FILE *fp = fopen(tempCert, "w");
+		fprintf(fp, "%s", ShmOCPP16Data->InstallCertificate.certificate);
+		fclose(fp);
 
+		//=====================================================
+		// Verify if the certificate is valid or not. (OCSP?)
+		//=====================================================
 		/*
-		 * 	TODO:	Install certificate process
-		 */
+		// Get ocsp url
+		char ocspUrl[512];
+		sprintf(temp ,"openssl x509 -noout -ocsp_uri -in %s", tempCert);
+		fp = popen(temp, "r");
+		if(fp)
+		{
+			while(fgets(temp, sizeof(temp), fp) != NULL)
+			{
+				if(strstr(temp, "://") != NULL)
+				{
+					strcpy(ocspUrl, temp);
+				}
+			}
+		}
+
+		// Get certificate chain for issuer
+		 * openssl s_client -connect [serverURL:port] -showcerts | sed -n '/-----BEGIN/,/-------END/p' > tempChain.pem
+		 *
+
+		// Execute OCSP
+		sprintf(temp ,"openssl ocsp -issuer tempChain.pem -cert /Storage/OCPP/tempInstallCertificate.pem -text -url %s", ocspUrl);
+		fp = popen(temp, "r");
+		if(fp)
+		{
+			while(fgets(temp, sizeof(temp), fp) != NULL)
+			{
+				if(strstr(temp, "tempInstallCertificate.pem: good") != NULL)
+				{
+					sprintf((char*)ShmOCPP16Data->InstallCertificate.Response_status, "Accepted");
+					break;
+				}
+			}
+		}
+
+		system("rm -f /Storage/OCPP/tempChain.pem");
+		pclose(fp);
+		*/
+
+		// Check the expired date (exp: notAfter=Oct  2 18:10:27 2048 GMT)
+		char strExpDate[30];
+		sprintf(temp ,"openssl x509 -noout -enddate -in /Storage/OCPP/tempInstallCertificate.pem");
+		fp = popen(temp, "r");
+		if(fp)
+		{
+			while(fgets(temp, sizeof(temp), fp) != NULL)
+			{
+				if(strstr(temp, "notAfter=") != NULL)
+				{
+					DEBUG_INFO("Certificate enddate info: %s\n", temp);
+					sscanf(temp, "%*[^=]=%[^G]G", strExpDate);
+					break;
+				}
+			}
+		}
+		DEBUG_INFO("ExpDate: %s\n", strExpDate);
+		struct tm tmExpDate;
+		struct timeb tbExpDate;
+		strptime(strExpDate, "%b  %d %H:%M:%S %Y", &tmExpDate);
+		tbExpDate.time = mktime(&tmExpDate);
+
+		if(DiffTimebWithNowSec(tbExpDate) >= 0)
+		{
+			DEBUG_INFO("The enddate is already expired...\n");
+			sprintf((char*)ShmOCPP16Data->InstallCertificate.Response_status, "Rejected");
+			goto End;
+		}
+
+		// Verify certificate with rootCA
+		sprintf(temp ,"openssl verify -CAfile /root/cacert.pem /Storage/OCPP/tempInstallCertificate.pem");
+		fp = popen(temp, "r");
+		if(fp)
+		{
+			while(fgets(temp, sizeof(temp), fp) != NULL)
+			{
+				if((strstr(temp, "tempInstallCertificate.pem: OK") != NULL) || (strstr(temp, "self signed certificate") != NULL))
+				{
+					sprintf((char*)ShmOCPP16Data->InstallCertificate.Response_status, "Accepted");
+					break;
+				}
+			}
+		}
+
+		if(strcmp((char*)ShmOCPP16Data->InstallCertificate.Response_status, "Accepted") != 0)
+		{
+			DEBUG_INFO("Cannot pass the openssl CA verifying...\n");
+			goto End;
+		}
+		else
+		{
+			if(strcmp((char*)ShmOCPP16Data->InstallCertificate.certificateType, "CentralSystemRootCertificate") == 0)
+			{
+				if(access("/Storage/OCPP/CentralSystemRootCertificate.pem",F_OK) != -1)
+				{
+					DEBUG_INFO("Existed CentralSystemRootCertificate is found. Replacing...\n");
+					rename("/Storage/OCPP/CentralSystemRootCertificate.pem", "/Storage/OCPP/CentralSystemRootCertificate_fallback.pem");
+					rename(tempCert, "/Storage/OCPP/CentralSystemRootCertificate.pem");
+				}
+				else
+				{
+					DEBUG_INFO("No existed CentralSystemRootCertificate. Creating...\n");
+					rename(tempCert, "/Storage/OCPP/CentralSystemRootCertificate.pem");
+				}
+			}
+			else if(strcmp((char*)ShmOCPP16Data->InstallCertificate.certificateType, "ManufacturerRootCertificate") == 0)
+			{
+				if(access("/Storage/OCPP/ManufacturerRootCertificate.pem",F_OK) != -1)
+				{
+					DEBUG_INFO("Existed ManufacturerRootCertificate is found. Replacing...\n");
+					rename("/Storage/OCPP/ManufacturerRootCertificate.pem", "/Storage/OCPP/ManufacturerRootCertificate_fallback.pem");
+					rename(tempCert, "/Storage/OCPP/ManufacturerRootCertificate.pem");
+				}
+				else
+				{
+					DEBUG_INFO("No existed ManufacturerRootCertificate. Creating...\n");
+					rename(tempCert, "/Storage/OCPP/ManufacturerRootCertificate.pem");
+				}
+			}
+		}
+		// Combine the installed rootCert to cacert
+
 		ShmOCPP16Data->MsMsg.bits.InstallCertificateReq = 1;
-		DEBUG_INFO("certificateType: %s\n", (char*)ShmOCPP16Data->InstallCertificate.certificateType);
-		DEBUG_INFO("certificate: %s\n", (char*)ShmOCPP16Data->InstallCertificate.certificate);
+	}
+
+End:
+	sendInstallCertificateConfirmation(uuid);
 
-		sprintf((char*)ShmOCPP16Data->InstallCertificate.Response_status, "Rejected");
-		sendInstallCertificateConfirmation(uuid);
+	if(strcmp((char*)ShmOCPP16Data->InstallCertificate.Response_status, "Accepted") != 0)
+	{
+		sprintf((char*)ShmOCPP16Data->SecurityEventNotification.type, "InvalidCentralSystemCertificate");
+		memset(ShmOCPP16Data->SecurityEventNotification.techInfo, 0x00, ARRAY_SIZE(ShmOCPP16Data->SecurityEventNotification.techInfo));
+		ShmOCPP16Data->SpMsg.bits.SecurityEventNotificationReq = 1;
 	}
+
 	json_object_put(InstallCertificate);
 
 	return result;
@@ -15965,6 +16465,7 @@ void *SignedUpdateFirmwareProcess(void *data)
 
 		do
 		{
+			sleep(1);
 			ShmOCPP16Data->SignedFirmwareStatusNotification.requestId = ShmOCPP16Data->SignedUpdateFirmware.requestId;
 			sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "Downloading");
 			ShmOCPP16Data->SpMsg.bits.SignedFirmwareStatusNotificationReq = 1;
@@ -15977,7 +16478,7 @@ void *SignedUpdateFirmwareProcess(void *data)
 				sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "DownloadFailed");
 				ShmOCPP16Data->SpMsg.bits.SignedFirmwareStatusNotificationReq = 1;
 
-				if(ShmOCPP16Data->SignedUpdateFirmware.retries>0)sleep(ShmOCPP16Data->SignedUpdateFirmware.retryInterval);else sleep(1);
+				if(ShmOCPP16Data->SignedUpdateFirmware.retries>0)sleep(ShmOCPP16Data->SignedUpdateFirmware.retryInterval);else sleep(3);
 
 				ShmOCPP16Data->SignedFirmwareStatusNotification.requestId = ShmOCPP16Data->SignedUpdateFirmware.requestId;
 				sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "Idle");
@@ -16042,6 +16543,7 @@ void *SignedUpdateFirmwareProcess(void *data)
 
 		do
 		{
+			sleep(1);
 			ShmOCPP16Data->SignedFirmwareStatusNotification.requestId = ShmOCPP16Data->SignedUpdateFirmware.requestId;
 			sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "Downloading");
 			ShmOCPP16Data->SpMsg.bits.SignedFirmwareStatusNotificationReq = 1;
@@ -16050,13 +16552,13 @@ void *SignedUpdateFirmwareProcess(void *data)
 			isSuccess = sftpDownLoadFile(host1, user, port, ftppath, firmwareFileName, (char*)ShmOCPP16Data->SignedUpdateFirmware.firmware.location);
 			if(!isSuccess)
 			{
-				//BulldogUtil.sleepMs(interval*1000);
+				sleep(1);
 				DEBUG_INFO("Update firmware request and download file fail.\n");
 				ShmOCPP16Data->SignedFirmwareStatusNotification.requestId = ShmOCPP16Data->SignedUpdateFirmware.requestId;
 				sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "DownloadFailed");
 				ShmOCPP16Data->SpMsg.bits.SignedFirmwareStatusNotificationReq = 1;
 
-				if(ShmOCPP16Data->SignedUpdateFirmware.retries>0)sleep(ShmOCPP16Data->SignedUpdateFirmware.retryInterval);else sleep(1);
+				if(ShmOCPP16Data->SignedUpdateFirmware.retries>0)sleep(ShmOCPP16Data->SignedUpdateFirmware.retryInterval);else sleep(3);
 
 				ShmOCPP16Data->SignedFirmwareStatusNotification.requestId = ShmOCPP16Data->SignedUpdateFirmware.requestId;
 				sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "Idle");
@@ -16131,6 +16633,7 @@ void *SignedUpdateFirmwareProcess(void *data)
 
 		do
 		{
+			sleep(1);
 			ShmOCPP16Data->SignedFirmwareStatusNotification.requestId = ShmOCPP16Data->SignedUpdateFirmware.requestId;
 			sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "Downloading");
 			ShmOCPP16Data->SpMsg.bits.SignedFirmwareStatusNotificationReq = 1;
@@ -16145,7 +16648,7 @@ void *SignedUpdateFirmwareProcess(void *data)
 				sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "DownloadFailed");
 				ShmOCPP16Data->SpMsg.bits.SignedFirmwareStatusNotificationReq = 1;
 
-				if(ShmOCPP16Data->SignedUpdateFirmware.retries>0)sleep(ShmOCPP16Data->SignedUpdateFirmware.retryInterval);else sleep(1);
+				if(ShmOCPP16Data->SignedUpdateFirmware.retries>0)sleep(ShmOCPP16Data->SignedUpdateFirmware.retryInterval);else sleep(3);
 
 				ShmOCPP16Data->SignedFirmwareStatusNotification.requestId = ShmOCPP16Data->SignedUpdateFirmware.requestId;
 				sprintf((char*)ShmOCPP16Data->SignedFirmwareStatusNotification.status, "%s", "Idle");
@@ -16687,7 +17190,7 @@ int initialConfigurationTable(void)
 		fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","AuthorizationCacheEnabled", "false", ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizationCacheEnabled].ItemData);
 
 		//AuthorizeRemoteTxRequests
-		ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemAccessibility = 0;
+		ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemAccessibility = 1;
 		strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemName, "AuthorizeRemoteTxRequests");
 		strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemData, "FALSE" );
 
@@ -17724,7 +18227,7 @@ void StoreConfigurationTable(void)
 
 	//AuthorizeRemoteTxRequests
 	/*
-	ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemAccessibility = 0;
+	ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemAccessibility = 1;
 	strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemName, "AuthorizeRemoteTxRequests");
 	strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[AuthorizeRemoteTxRequests].ItemData, "TRUE" );
 	*/
@@ -22597,6 +23100,12 @@ void FillStartTransaction(int ConnectorId, unsigned char IdTag[], int MeterStart
 	strcpy((char *)ShmOCPP16Data->StartTransaction[ConnectorId-1].Timestamp,(char *) Timestamp);
 }
 
+void FillTransactionId(int ConnectorId, int TransactionId)
+{
+	ShmOCPP16Data->StartTransaction[ConnectorId-1].ConnectorId = ConnectorId;
+	ShmOCPP16Data->StartTransaction[ConnectorId-1].ResponseTransactionId = TransactionId;
+}
+
 int GetWebSocketPingInterval(void)
 {
 	return atoi((const char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[WebSocketPingInterval].ItemData);