diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs index 6a6ac01..83d8e56 100644 --- a/AssemblyInfo.cs +++ b/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.7.1.0")] -[assembly: AssemblyFileVersion("1.7.1.0")] +[assembly: AssemblyVersion("1.8.0.0")] +[assembly: AssemblyFileVersion("1.8.0.0")] diff --git a/Packets/ProtocolBase.cs b/Packets/ProtocolBase.cs index 53d5b92..7b7bd23 100644 --- a/Packets/ProtocolBase.cs +++ b/Packets/ProtocolBase.cs @@ -93,9 +93,10 @@ public virtual bool WriteFlash(string version, byte[] data) for (var i = 0; i < subData.Length; i++) subData[i] = 0xff; Array.Copy(data, blockOffset, subData, 0, blockLength); - subData = EncryptFlashProcess(subData); + var cipher = new byte[subData.Length]; + EncryptFlashProcess(subData, 0, cipher, 0, cipher.Length); var chunkNumber = (ushort)(absOffset / chunkSize); - _device.Send(CreatePacketFlashWriteReq(chunkNumber, chunkCount, subData, blockLength, seqId)); + _device.Send(CreatePacketFlashWriteReq(chunkNumber, chunkCount, cipher, blockLength, seqId)); for (var counter = 0; ; counter++) { packet = _device.Recv(); @@ -149,9 +150,9 @@ public virtual void EncryptFlashFinish() { } - public virtual byte[] EncryptFlashProcess(byte[] data) + public virtual void EncryptFlashProcess(byte[] src, int srcIndex, byte[] dst, int dstIndex, int length) { - return data; + Array.Copy(src, srcIndex, dst, dstIndex, length); } public virtual void DecryptFlashInit() @@ -162,9 +163,9 @@ public virtual void DecryptFlashFinish() { } - public virtual byte[] DecryptFlashProcess(byte[] data) + public virtual void DecryptFlashProcess(byte[] src, int srcIndex, byte[] dst, int dstIndex, int length) { - return data; + Array.Copy(src, srcIndex, dst, dstIndex, length); } #endregion Bootloader diff --git a/Packets/V5/ProtocolV5.cs b/Packets/V5/ProtocolV5.cs index c647f73..ef50827 100644 --- a/Packets/V5/ProtocolV5.cs +++ b/Packets/V5/ProtocolV5.cs @@ -71,18 +71,27 @@ public override PacketFlashWriteAck CreatePacketFlashWriteAck(ushort chunkNumber Utils.FromHex("8172ea14916b606855ff2aabe52e993c"), // iv 15 }; + private static void GetKey(int keyNumber, out byte[] key, out byte[] iv) + { + if (keyNumber < 0 || keyNumber >= 0x10) + throw new ArgumentOutOfRangeException("keyNumber"); + key = _keys[keyNumber * 2 + 0]; + iv = _keys[keyNumber * 2 + 1]; + key = ReverseBytesU32(key); + iv = ReverseBytesU32(iv); + } + private ICryptoTransform _aesEncoder; public override void EncryptFlashInit() { - // WARNING: do not remove exception, with no proper key it can brick your radio - throw new NotImplementedException("AES encrypted flash upload is not tested yet"); - var key = _keys[_keyNumber * 2 + 0]; - var iv = _keys[_keyNumber * 2 + 1]; + byte[] key; + byte[] iv; + GetKey(_keyNumber, out key, out iv); using (var aes = Aes.Create()) { - aes.Key = ReverseBytesU32(key); - aes.IV = ReverseBytesU32(iv); + aes.Key = key; + aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.None; aes.BlockSize = 128; @@ -90,15 +99,6 @@ public override void EncryptFlashInit() } } - private static byte[] ReverseBytesU32(byte[] data) - { - return Enumerable.Range(0, data.Length / 4) - .Select(arg => BitConverter.ToUInt32(data, arg * 4)) - .Select(arg => BitConverter.ToUInt32(BitConverter.GetBytes(arg).Reverse().ToArray(), 0)) - .SelectMany(arg => BitConverter.GetBytes(arg)) - .ToArray(); - } - public override void EncryptFlashFinish() { if (_aesEncoder != null) @@ -108,23 +108,22 @@ public override void EncryptFlashFinish() } } - public override byte[] EncryptFlashProcess(byte[] data) + public override void EncryptFlashProcess(byte[] src, int srcIndex, byte[] dst, int dstIndex, int length) { - var encoded = new byte[data.Length]; - _aesEncoder.TransformBlock(data, 0, data.Length, encoded, 0); - return encoded; + _aesEncoder.TransformBlock(src, srcIndex, length, dst, dstIndex); } private ICryptoTransform _aesDecoder; public override void DecryptFlashInit() { - var key = _keys[_keyNumber * 2 + 0]; - var iv = _keys[_keyNumber * 2 + 1]; + byte[] key; + byte[] iv; + GetKey(_keyNumber, out key, out iv); using (var aes = Aes.Create()) { - aes.Key = ReverseBytesU32(key); - aes.IV = ReverseBytesU32(iv); + aes.Key = key; + aes.IV = iv; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.None; aes.BlockSize = 128; @@ -141,11 +140,18 @@ public override void DecryptFlashFinish() } } - public override byte[] DecryptFlashProcess(byte[] data) + public override void DecryptFlashProcess(byte[] src, int srcIndex, byte[] dst, int dstIndex, int length) + { + _aesDecoder.TransformBlock(src, srcIndex, length, dst, dstIndex); + } + + private static byte[] ReverseBytesU32(byte[] data) { - var encoded = new byte[data.Length]; - _aesDecoder.TransformBlock(data, 0, data.Length, encoded, 0); - return encoded; + return Enumerable.Range(0, data.Length / 4) + .Select(arg => BitConverter.ToUInt32(data, arg * 4)) + .Select(arg => BitConverter.ToUInt32(BitConverter.GetBytes(arg).Reverse().ToArray(), 0)) + .SelectMany(arg => BitConverter.GetBytes(arg)) + .ToArray(); } } } diff --git a/Program.cs b/Program.cs index d443357..1de40b4 100644 --- a/Program.cs +++ b/Program.cs @@ -389,8 +389,8 @@ private static int OnCommand_Simula(string name, string[] v) Envelope.IsRadioEndpoint = true; using (var device = new Device(name)) // "/dev/serial0" { - var protocol = ProtocolBase.CreateV2(device); - //var protocol = ProtocolBase.CreateV5(device); + //var protocol = ProtocolBase.CreateV2(device); + var protocol = ProtocolBase.CreateV5(device); var isMute = false; byte[] fwdata = null; string fwvers = null; @@ -435,16 +435,17 @@ private static int OnCommand_Simula(string name, string[] v) fwdata = buf; } } + device.Send(protocol.CreatePacketFlashWriteAck(packetWrite.ChunkNumber, packetWrite.SequenceId)); + //Array.Copy(packetWrite.Data, 0, fwdata, packetWrite.Offset, packetWrite.Size); - var page = new byte[0x100]; + var page = new byte[0x100]; Array.Copy(packetWrite.RawData, 16, page, 0, Math.Min(page.Length, packetWrite.HdrSize - 12)); - page = protocol.DecryptFlashProcess(page); - Array.Copy(page, 0, fwdata, packetWrite.ChunkNumber*0x100, packetWrite.HdrSize - 12); + protocol.DecryptFlashProcess(page, 0, fwdata, packetWrite.ChunkNumber * 0x100, packetWrite.HdrSize - 12); // detect flashing complete event if (packetWrite.ChunkNumber == packetWrite.ChunkCount-1) { - protocol.DecryptFlashInit(); + protocol.DecryptFlashFinish(); var shrink = 0x100 - packetWrite.Size; //var shrink = 0; var buf = new byte[fwdata.Length - shrink]; @@ -454,9 +455,8 @@ private static int OnCommand_Simula(string name, string[] v) Console.WriteLine("Write {0}", fileName); File.WriteAllBytes(fileName, fwdata); fwdata = null; + return 0; } - - device.Send(protocol.CreatePacketFlashWriteAck(packetWrite.ChunkNumber, packetWrite.SequenceId)); } isMute = true; }