diff --git a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterPwdFile.cs b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterPwdFile.cs index 69e0cfd1..55b4f503 100644 --- a/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterPwdFile.cs +++ b/Common/Hardware/WaterMeter/Genesis/GenesisFile/MeterPwdFile.cs @@ -223,6 +223,64 @@ namespace Xylem.Common.Hardware.WaterMeter.Genesis.GenesisFile return true; } + /// + /// Check the hashed password file: + /// - Checks if password level 8 is unequal to skeleton key + /// - Checks if password level 3 is unequal to password level 8 (level 3 may be overwritten by level 8 + /// password hash) + /// - Builds skeleton key password hash and checks if this is placed at password level 3, + /// - Builds password level 8 hash and checks if this is placed at level 8. + /// + /// + /// SkeletonKey for comparison + /// + /// + /// + /// - Initial. + /// + public Boolean CheckHashedPwdFile(Byte[] pwdFile, String skeletonKey, String pwdLevel8) + { + + var retVal = false; + // the skeletonKey has to be unequally to the passwordLvl8 + if (skeletonKey.Equals(pwdLevel8)) + { + return false; + } + + // compare hashed skeletonKey and passwordLvl8 + for (var c = 0; c < MeterPwdDb.HashedPwdLength; c++) + { + // hashed level 3 and level 8 have to be unequal on at least one byte position + if (pwdFile[MeterPwdDb.SkeletonKeyIdx * MeterPwdDb.HashedPwdLength + c] != + pwdFile[MeterPwdDb.PwdLevel8Idx * MeterPwdDb.HashedPwdLength + c]) + { + retVal = true; + break; + } + } + + // hash the skeleton and check if equal to hashed level 3 + // hash the passwordLvl8 and check if equal to hashed level 8 + using (var sha1 = new System.Security.Cryptography.SHA1Managed()) + { + var skeletonHash = sha1.ComputeHash(Encoding.UTF8.GetBytes(skeletonKey)); + var passwordLvl8Hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(pwdLevel8)); + + for (var c = 0; c < MeterPwdDb.HashedPwdLength; c++) + { + // if any byte is different the passwords do not match + if (pwdFile[MeterPwdDb.SkeletonKeyIdx * MeterPwdDb.HashedPwdLength + c] != skeletonHash[c] || + pwdFile[MeterPwdDb.PwdLevel8Idx * MeterPwdDb.HashedPwdLength + c] != passwordLvl8Hash[c]) + { + return false; + } + } + } + + return retVal; + } + /// /// Build skeleton key out of unique processor Id /// diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs index 435738e9..2d014734 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateBuilder/FrmFwUpdateBuilder.cs @@ -1341,14 +1341,14 @@ namespace Xylem.ServiceFwUpdate.Ui.FwUpdateBuilder fwUpdateSafe.Updates.CordonelDeviceInfos = _cordonelUpdateList; ////TODO THW remove this DEBUG to map from current selection to TEST BOARD - //_cordonelUpdateList[0].CustomerSerialNumber = "8 SEN20 1975 6272"; - //_cordonelUpdateList[0].PcbId = "182100041"; - //GetPwdFromDb(_cordonelUpdateList[0]); - //fwUpdateSafe.License.Build = 5; - //var dateTime = fwUpdateSafe.License.ValidTo.AddDays(-1); - //fwUpdateSafe.License.ValidTo = dateTime; - //var addDays = fwUpdateSafe.SafeInfo.FwUpdateValidDate.AddDays(-1); - //fwUpdateSafe.SafeInfo.FwUpdateValidDate = addDays; + _cordonelUpdateList[0].CustomerSerialNumber = "8 SEN20 1975 6272"; + _cordonelUpdateList[0].PcbId = "182100041"; + GetPwdFromDb(_cordonelUpdateList[0]); + fwUpdateSafe.License.Build = 5; + var dateTime = fwUpdateSafe.License.ValidTo.AddDays(-1); + fwUpdateSafe.License.ValidTo = dateTime; + var addDays = fwUpdateSafe.SafeInfo.FwUpdateValidDate.AddDays(-1); + fwUpdateSafe.SafeInfo.FwUpdateValidDate = addDays; ////TODO THW remove this DEBUG to map from current selection to TEST BOARD var serializedData = JsonConvert.SerializeObject(fwUpdateSafe); diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/FrmServiceFwUpdateSw.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/FrmServiceFwUpdateSw.cs index 406f4095..318e3383 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/FrmServiceFwUpdateSw.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/FrmServiceFwUpdateSw.cs @@ -52,6 +52,8 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw private GenesisMeter _currentGenesis; private readonly MeterBatch _meterBatch; private Byte[] _hashedPwdFile; + private String _passwordLvl8; + private String _skeletonKey; // port settings private MeterPortScanner _serialPortScanner; @@ -3006,15 +3008,15 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw } // Search the PCB ID and extract password for login - String password = null; - String skeletonKey = null; + _skeletonKey = null; + _passwordLvl8 = null; _genesisInUpdateList = false; if (_cordonelDeviceInfos != null) { foreach (var device in _cordonelDeviceInfos.Where(device => _currentGenesis.PcbId == device.PcbId)) { - skeletonKey = device.PwdContainer.SkeletonKey; - password = device.PwdContainer.PasswordLvl8; + _skeletonKey = device.PwdContainer.SkeletonKey; + _passwordLvl8 = device.PwdContainer.PasswordLvl8; if (!string.IsNullOrEmpty(device.CustomerSerialNumber)) _customerSerialNumber = device.CustomerSerialNumber; @@ -3026,7 +3028,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw } } - if (password == null || skeletonKey == null) + if (_passwordLvl8 == null || _skeletonKey == null) { _processState = ProcessState.Error; return false; @@ -3038,7 +3040,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw // This login may be time consuming on readout of application information // first try to login with password Level 8, this is needed if the password file is installed - if (LoginAndSpecialSetupProcedure(password)) + if (LoginAndSpecialSetupProcedure(_passwordLvl8)) { LogText(Resources.StrLoginPwdLevel8); _passwordFileIsCorrupted = false; @@ -3057,7 +3059,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw Thread.Sleep(5000); // Use the skeleton key for login as the password file may not be installed or invalid - if (LoginAndSpecialSetupProcedure(skeletonKey)) + if (LoginAndSpecialSetupProcedure(_skeletonKey)) { LogText(Resources.StrLoginSkeletonKey); return true; @@ -3736,13 +3738,12 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw return; } - //TODO THW avoid installation of password file if hash of level 3 equals level 8 - //TODO THW avoid installation if password file level 3 is unequal hashed skeletonKey - //TODO THW avoid installation if password file level 8 is unequal hashed password InfoProcessActive(lblPasswordFileCheck, Resources.StrPasswordFileRestoreActive); // try to install password, first get the password file from device info var pwdFileObject = new MeterPwdFile(_currentGenesis); - if (_hashedPwdFile != null && _hashedPwdFile.Length == MeterPwdDb.PwdFileLength) + if (_hashedPwdFile != null && + _hashedPwdFile.Length == MeterPwdDb.PwdFileLength && + pwdFileObject.CheckHashedPwdFile(_hashedPwdFile , _skeletonKey, _passwordLvl8)) { SetControlsCommunicationActive(); _currentGenesis?.ReLogin(); @@ -3768,7 +3769,7 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw // the password file is NOT in the password container else { - InfoProcessFailed(lblPasswordFileCheck, Resources.StrPasswordNotDelivered); + InfoProcessFailed(lblPasswordFileCheck, Resources.StrPasswordFileFromSafeInvalid); _processState = errorExitState; } diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.Designer.cs b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.Designer.cs index 82a8f624..5652a101 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.Designer.cs +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.Designer.cs @@ -745,6 +745,15 @@ namespace Xylem.ServiceFwUpdate.Ui.ServiceFwUpdateSw.Properties { } } + /// + /// Looks up a localized string similar to ERROR: Password file from FW update safe is invalid!. + /// + internal static string StrPasswordFileFromSafeInvalid { + get { + return ResourceManager.GetString("StrPasswordFileFromSafeInvalid", resourceCulture); + } + } + /// /// Looks up a localized string similar to ERROR: Password file not installed or invalid!. /// diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.de.resx b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.de.resx index ed4d5f64..c3ae07a8 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.de.resx +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.de.resx @@ -604,4 +604,7 @@ FW-Update Builderoperator ID: + + FEHLER: Paßwortdatei vom FW Update Safe ist ungültig! + \ No newline at end of file diff --git a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.resx b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.resx index b9f53c7c..1cf5292e 100644 --- a/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.resx +++ b/ServiceFwUpdate/Ui/ServiceFwUpdateSw/Properties/Resources.resx @@ -604,4 +604,7 @@ FW-Update Builder Operator ID: + + ERROR: Password file from FW update safe is invalid! + \ No newline at end of file