//Security Access private bool RequestSecurityAccess(EdiabasNet ediabas) { Checksums_Signatures ChecksumsSignatures = new Checksums_Signatures(); this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Requesting Security Access"; }); if (!ExecuteJob(ediabas, "seriennummer_lesen", string.Empty)) { return(false); } byte[] serialReply = GetResult_ByteArray("_TEL_ANTWORT", ediabas.ResultSets); byte[] serialNumber = serialReply.Skip(serialReply.Length - 5).Take(4).ToArray(); //DME uses last 4 bytes of serial number in authentication message byte[] userID = new byte[4]; //user ID can be any 4 bytes. Random rng = new Random(); rng.NextBytes(userID); //Probably a bit wasteful to use a random number generator over pulling 4 bytes out of my ass, but whatever. if (!ExecuteJob(ediabas, "authentisierung_zufallszahl_lesen", "3;0x" + BitConverter.ToUInt32(userID.Reverse().ToArray(), 0).ToString("X"))) //Request random number, passing the "userID" generated above as an argument { return(false); } byte[] seed = GetResult_ByteArray("ZUFALLSZAHL", ediabas.ResultSets); //DME sends a random number if (!ExecuteJob(ediabas, "authentisierung_start", ChecksumsSignatures.GetSecurityAccessMessage(userID, serialNumber, seed))) //Sign message using level 3 private key. If DME decrypts successfully and it matches its own calculation, security access is granted { return(false); } if (Global.diagProtocol != "BMW-FAST") //If not using the BMW-FAST protocol (BN2000 cars, i.e E60/E65 MS45), raise baudrate (from 9600 default) to 115200 { //Could add an option to lower baudrate for scenarios where it doesn't work. //On the other hand, probably shouldn't encourage flashing with an unstable connection if (!ExecuteJob(ediabas, "diagnose_mode", "ECUPM;PC115200")) //Request ECUProgramming mode @ baudrate 115200 { return(false); } if (!ExecuteJob(ediabas, "SET_PARAMETER", ";115200")) //Sets serial port baudrate to 115200 { return(false); } if (!ExecuteJob(ediabas, "ACCESS_TIMING_PARAMETER", "00;120;24;240;00")) //WinKFP does this -- not 100% sure of what it actually changes. If job is skipped, communications don't work //If not set to what the specific module wants, the job doesn't execute. { return(false); } if (!ExecuteJob(ediabas, "SET_PARAMETER", ";115200;;15")) { return(false); } } else //"BMW-FAST" cars communicate @ 115200 natively and don't need all those parameters set { if (!ExecuteJob(ediabas, "diagnose_mode", "ECUPM")) { return(false); } } return(true);//Should be in ECU Programming Mode now }
private async void Flashfull() { Checksums_Signatures ChecksumsSignatures = new Checksums_Signatures(); bool success = true; using (EdiabasNet ediabas = StartEdiabas()) { await Task.Run(() => { if (!RequestSecurityAccess(ediabas)) { success = false; this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Security Access Denied"; }); } }); uint eraseStart = 0x2060000; uint eraseBlock = 0xA0000; uint flashStart = 0x2060000; uint flashEnd = 0x20FFF3F; uint flashMPCStart = 0; uint flashMPCEnd = 0x6FFFF; if (Global.diagProtocol == "BMW-FAST") { if (!ExecuteJob(ediabas, "normaler_datenverkehr", "nein;nein;ja")) { return; } if (!ExecuteJob(ediabas, "normaler_datenverkehr", "ja;nein;nein")) { return; } } this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Erasing Flash"; }); await Task.Run(() => success = EraseECU(ediabas, eraseBlock, eraseStart)); byte[] toFlash = null; toFlash = ChecksumsSignatures.CorrectProgramChecksums(Global.openedFlash, Global.openedMPC); toFlash = ChecksumsSignatures.SignMS45Program(toFlash, Global.openedMPC).Skip(0x60000).Take(0x9FF40).ToArray(); this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Flashing External Program"; }); await Task.Run(() => success = FlashBlock(ediabas, toFlash, flashStart, flashEnd)); toFlash = null; toFlash = Global.openedMPC; this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Flashing Internal Program"; }); await Task.Run(() => success = FlashBlock(ediabas, toFlash, flashMPCStart, flashMPCEnd)); if (success) { await Task.Run(() => { if (Global.diagProtocol != "BMW-FAST") { if (!ExecuteJob(ediabas, "diagnose_mode", "DEFAULT;PC9600")) { success = false; return; } if (!ExecuteJob(ediabas, "SET_PARAMETER", ";9600")) { success = false; return; } } else { if (!ExecuteJob(ediabas, "normaler_datenverkehr", "ja;nein;ja")) { success = false; return; } } if (!ExecuteJob(ediabas, "FLASH_PROGRAMMIER_STATUS_LESEN", String.Empty)) { success = false; return; } this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Checking signature"; }); if (!ExecuteJob(ediabas, "FLASH_SIGNATUR_PRUEFEN", "Programm;64")) { this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Signature check failed"; }); success = false; if (!ExecuteJob(ediabas, "STEUERGERAETE_RESET", String.Empty)) { return; } return; } if (!ExecuteJob(ediabas, "FLASH_PROGRAMMIER_STATUS_LESEN", String.Empty)) { success = false; return; } this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Resetting ECU"; }); if (!ExecuteJob(ediabas, "STEUERGERAETE_RESET", String.Empty)) { return; } }); if (success) { this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Flash successful"; }); } else { this.Dispatcher.Invoke(() => { statusTextBlock.Text = "Flash failed"; }); } } IdentDME(); return; } }