public static byte[] Encrypt(byte[] fileData, CMFileType fileType) { using (MemoryStream stream = new MemoryStream()) using (BinaryWriter writer = new BinaryWriter(stream)) { byte[] fileTypeStrBuffer = new byte[8]; Buffer.BlockCopy(fileTypes[fileType], 0, fileTypeStrBuffer, 0, fileTypes[fileType].Length); string fileTypeStr = Encoding.ASCII.GetString(fileTypeStrBuffer).TrimEnd('\0'); ushort encryptionKey = Crc16.GetCrc(Encoding.ASCII.GetBytes(fileTypeStr)); encryptionKey = Crc16.GetCrc(fileTypeStrBuffer, 0, encryptionKey); byte[] encryptedData = new byte[fileData.Length]; Buffer.BlockCopy(fileData, 0, encryptedData, 0, fileData.Length); ushort dataCrc = Encrypt(encryptedData, encryptionKey); // Offset 0 (file signature) writer.Write(fileSignature); // Offset 4 (header crc - to be built after the header is fully formed) writer.Write((int)0); // Offset 8 (timestamp) writer.Write(GetTimeStamp(DateTime.Now)); // Offset 12 (data length) writer.Write(fileData.Length); // Offset 16 (data crc) writer.Write((int)dataCrc); // Offset 20 (file type) writer.Write((int)fileType); // Offset 24-32 (file type string) for (int i = 0; i < 8; i++) { writer.Write((byte)(i < fileTypeStrBuffer.Length ? fileTypeStrBuffer[i] : 0)); } writer.Write(encryptedData); // Get the header bytes, calculate the crc, and insert the crc into the header long tempPos = stream.Position; stream.Position = 0; byte[] header = new byte[32]; stream.Read(header, 0, header.Length); ushort headerCrc = Crc16.GetCrc(header); stream.Position = 4; writer.Write(headerCrc); stream.Position = tempPos; return(stream.ToArray()); } }
private static byte[] Decrypt(byte[] buffer, string file) { using (MemoryStream stream = new MemoryStream(buffer)) using (BinaryReader reader = new BinaryReader(stream)) { if (reader.ReadUInt32() != fileSignature) { Log("Bad file signature", buffer, file); return(null); } // Header crc is at offset 4, written as 4 bytes (but still a crc16) // (this is a crc of the first 32 bytes (where the crc bytes are 0) stream.Position = 4; ushort headerCrc = reader.ReadUInt16(); // Timestamp is never used // Timestamp is at offset 8, written as 4 bytes // stream.Position = 8; // int timestamp = reader.ReadInt32(); // Length is at offset 12, written as 4 bytes stream.Position = 12; int dataLength = reader.ReadInt32(); // Data crc is at offset 16, written as 4 bytes (but still a crc16) stream.Position = 16; ushort dataCrc = reader.ReadUInt16(); // File type is never used // File type is at offset 20, written as 4 bytes // stream.Position = 20; // int fileType = reader.ReadInt32(); // File type (string) is at offset 24, written as 8 bytes, padded with 00 stream.Position = 24; byte[] fileTypeStrBuffer = reader.ReadBytes(8); uint intFileType = BitConverter.ToUInt32(fileTypeStrBuffer, 0); if (unknownMaps.ContainsKey(intFileType)) { byte[] newType = BitConverter.GetBytes(unknownMaps[intFileType]); fileTypeStrBuffer = new byte[8]; Buffer.BlockCopy(newType, 0, fileTypeStrBuffer, 0, newType.Length); } List <byte> blob = new List <byte>(); for (int i = 0; i < fileTypeStrBuffer.Length; i++) { if (fileTypeStrBuffer[i] == 0) { break; } blob.Add(fileTypeStrBuffer[i]); } // First crc the file type name, then get crc the file type name (including zeroed bytes) ushort encryptionKey = Crc16.GetCrc(blob.ToArray()); encryptionKey = Crc16.GetCrc(fileTypeStrBuffer, 0, encryptionKey); // Data is at offset 32 stream.Position = 32; byte[] data = reader.ReadBytes(dataLength); ushort calculatedDataCrc = Decrypt(data, encryptionKey); if (dataCrc != calculatedDataCrc) { Log("File has an invalid data crc", buffer, file); } if (stream.Position != stream.Length) { Log("File has trailing bytes", buffer, file); } stream.Position = 0; byte[] header = reader.ReadBytes(32); header[4] = 0; header[5] = 0; header[6] = 0; header[7] = 0; ushort calculatedHeaderCrc = Crc16.GetCrc(header); if (headerCrc != calculatedHeaderCrc) { Log("File has an invalid header crc", buffer, file); } return(data); } }
public void SetMacros(KeyboardLayer layer, UserDataFile userData) { WritePacketNoResponse(OpCodes.LayerResetDataType, (byte)layer, null, (byte)KeyboardLayerDataType.Macros); // The following check has been disabled so that the WebGUI can assign macros without having to setup the keys /*if (userData.GetNumMacros(layer) == 0) * { * return; * }*/ using (Packet packet = new Packet()) { // TODO: This should be improved to only send the macros to the layers that require the macro foreach (UserDataFile.Macro macro in userData.Macros.Values) { if (macro.Id < 0) { continue; } if (macro.Actions.Count * 2 > byte.MaxValue) { Program.Log("Macro '" + macro.Name + "' has too many actions (" + macro.Actions.Count + ", limit is " + (byte.MaxValue / 2) + ")"); continue; } if (macro.Actions.Count == 0 && macro.Id >= 0) { Program.Log("Macro '" + macro.Name + "' doesn't have any actions!"); continue; } packet.WriteUInt16(0x55AA);// Macro magic (21930 / 0x55AA / AA 55) // Crc to be filled out once all data is written int crcIndex = packet.Index; packet.WriteUInt16(0); byte numActionInts = (byte)((macro.Actions.Count * 2) - (macro.UseTrailingDelay ? 0 : 1)); packet.WriteByte(numActionInts); packet.WriteByte((byte)macro.Id); packet.WriteByte((byte)macro.RepeatType); packet.WriteByte(macro.RepeatCount); int crcDataStartIndex = packet.Index; int crcDataEndIndex = packet.Index + (numActionInts * 4); for (int i = 0; i < 63; i++) { if (i < macro.Actions.Count) { UserDataFile.Macro.Action action = macro.Actions[i]; packet.WriteByte(action.KeyCode); packet.WriteByte((byte)action.Modifier); packet.WriteByte((byte)action.State); packet.WriteByte((byte)action.Type); if (i < macro.Actions.Count - 1 || (macro.UseTrailingDelay && i == macro.Actions.Count - 1)) { packet.WriteUInt16(action.Delay); //TODO: Investigate! (ushort)(action.Delay == 0 ? 0 : action.Delay / 2));// Delay seems to be doubled? packet.WriteByte(0); // Always 0? packet.WriteByte(3); // Always 3? (1/2 use no delay, 0/4 (and maybe others) seem to never stop pressing the key) } else { packet.WriteInt32(0); } } else { packet.WriteInt64(0); } } byte[] buffer = packet.GetBuffer(); byte[] bytesToCrc = new byte[crcDataEndIndex - crcDataStartIndex]; Buffer.BlockCopy(buffer, crcDataStartIndex, bytesToCrc, 0, bytesToCrc.Length); ushort crc = Crc16.GetCrc(bytesToCrc); // Always 0? packet.WriteByte(0); int tempIndex = packet.Index; packet.Index = crcIndex; packet.WriteUInt16(crc); packet.Index = tempIndex; } WritePacketNoResponse(OpCodes.LayerSetMacros, (byte)layer, packet); } }
private static KeyboardState Handshake(HidStream stream) { try { byte bufferSizeA; byte bufferSizeB; uint firmwareId; byte firmwareMinorVersion; byte firmwareMajorVersion; uint modelId; using (Packet packet = WriteSimplePacket(stream, 0x0901)) { if (packet == null) { LogHandshakeFailed(stream.Device, "opcode 01 09"); return(null); } bufferSizeA = packet.ReadByte(); bufferSizeB = packet.ReadByte(); if (bufferSizeA == 0 || bufferSizeB == 0) { LogHandshakeFailed(stream.Device, "Bad buffer size"); return(null); } } using (Packet packet = WriteSimplePacket(stream, 0x0101)) { if (packet == null) { LogHandshakeFailed(stream.Device, "opcode 01 01"); return(null); } firmwareId = packet.ReadUInt32(); firmwareMinorVersion = packet.ReadByte(); firmwareMajorVersion = packet.ReadByte(); if (firmwareId == 0 || (firmwareMinorVersion == 0 && firmwareMajorVersion == 0)) { LogHandshakeFailed(stream.Device, "Bad firmware id"); return(null); } } using (Packet packet = WriteSimplePacket(stream, 0x0801)) { if (packet == null) { LogHandshakeFailed(stream.Device, "opcode 01 08"); return(null); } byte[] crcBytes = packet.ReadBytes(6); ushort calculatedModelIdCrc = Crc16.GetCrc(crcBytes); packet.Index -= 6; modelId = packet.ReadUInt32(); if (modelId == 0) { LogHandshakeFailed(stream.Device, "Bad keyboard model id"); return(null); } ushort crcValidation1 = packet.ReadUInt16(); ushort modelIdCrc = packet.ReadUInt16(); if (calculatedModelIdCrc != modelIdCrc) { LogHandshakeFailed(stream.Device, "Bad keyboard model crc"); return(null); } } // OpCodes_Info.Unk_02 should probably also be sent? Not sure what it's used for though... KeyboardState result = KeyboardState.GetKeyboardState(modelId); if (result == null || result.FirmwareId != firmwareId) { LogHandshakeFailed(stream.Device, "Couldn't find data for keyboard"); return(null); } result.FirmwareMinorVersion = firmwareMinorVersion; result.FirmwareMajorVersion = firmwareMajorVersion; result.InitializeBuffers(bufferSizeA, bufferSizeB); return(result); } catch (Exception e) { LogHandshakeFailed(stream.Device, "Exception occured. " + e); return(null); } }
private static byte[] Decrypt(byte[] buffer, string file) { using (MemoryStream stream = new MemoryStream(buffer)) using (BinaryReader reader = new BinaryReader(stream)) { if (reader.ReadUInt32() != fileSignature) { Log("Bad file signature", buffer, file); return null; } // Header crc is at offset 4, written as 4 bytes (but still a crc16) // (this is a crc of the first 32 bytes (where the crc bytes are 0) stream.Position = 4; ushort headerCrc = reader.ReadUInt16(); // Timestamp is at offset 8, written as 4 bytes stream.Position = 8; int timestamp = reader.ReadInt32(); // Length is at offset 12, written as 4 bytes stream.Position = 12; int dataLength = reader.ReadInt32(); // Data crc is at offset 16, written as 4 bytes (but still a crc16) stream.Position = 16; ushort dataCrc = reader.ReadUInt16(); // File type is at offset 20, written as 4 bytes stream.Position = 20; int fileType = reader.ReadInt32(); // File type (string) is at offset 24, written as 8 bytes, padded with 00 stream.Position = 24; byte[] fileTypeStrBuffer = reader.ReadBytes(8); // First crc the file type name, then get crc the file type name (including zeroed bytes) string fileTypeStr = Encoding.ASCII.GetString(fileTypeStrBuffer).TrimEnd('\0'); ushort encryptionKey = Crc16.GetCrc(Encoding.ASCII.GetBytes(fileTypeStr)); encryptionKey = Crc16.GetCrc(fileTypeStrBuffer, 0, encryptionKey); // Data is at offset 32 stream.Position = 32; byte[] data = reader.ReadBytes(dataLength); ushort calculatedDataCrc = Decrypt(data, encryptionKey); if (dataCrc != calculatedDataCrc) { Log("File has an invalid data crc", buffer, file); } if (stream.Position != stream.Length) { Log("File has trailing bytes", buffer, file); } stream.Position = 0; byte[] header = reader.ReadBytes(32); header[4] = 0; header[5] = 0; header[6] = 0; header[7] = 0; ushort calculatedHeaderCrc = Crc16.GetCrc(header); if (headerCrc != calculatedHeaderCrc) { Log("File has an invalid header crc", buffer, file); } return data; } }