Пример #1
0
        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());
                }
        }
Пример #2
0
        private byte[] GetResponse(byte op1, byte op2)
        {
            // This is a bit of a hack to consume any packets sent from the keyboard which we didn't request
            // such as changing the keyboard layer manually. TODO: Add a proper packet handler and remove this hack.
            const int reportHeaderLen = 1;

            while (true)
            {
                byte[] resultBufferWithReportId = new byte[65];
                try
                {
                    stream.Read(resultBufferWithReportId);
                }
                catch
                {
                    return(null);
                }
                if (resultBufferWithReportId[0] != 0)
                {
                    return(null);
                }
                if (resultBufferWithReportId[1] == op1)
                {
                    byte[] resultBuffer = new byte[64];
                    Buffer.BlockCopy(resultBufferWithReportId, 1, resultBuffer, 0, resultBuffer.Length);
                    return(resultBuffer);
                }
                else if (resultBufferWithReportId[1] == (byte)OpCodes.DriverKeyCallback)
                {
                    byte callbackId      = resultBufferWithReportId[3];
                    bool callbackKeyDown = resultBufferWithReportId[4] != 0;
                    if (callbackKeyDown)
                    {
                        KeyboardState.Key key;
                        State.KeysByLogicCode.TryGetValue(callbackId, out key);
                        Program.Log("Index:" + callbackId + " " +
                                    (key == null ? "(null)" :
                                     "Name:" + key.KeyName + " " +                   // Name of the key
                                     "Indx:" + key.LogicCode + " " +                 // 'Indx' for logic code / key index
                                     "Loc:" + key.LocationCode + " " +               // 'Loc' for location code
                                     "D:0x" + key.DriverValue.ToString("X8") + " " + // 'D' for DriverValue
                                                                                     //"E:" + (DriverValue)key.DriverValue + " " +// 'E' for the Enum variant of the DriverValue
                                     "S:" + key.DriverValueName));                   // <--- 'S' for string representation (use this for mapping keys in your UserData file)
                    }
                }
                else if (!Crc16.ValidateCrc(resultBufferWithReportId, reportHeaderLen, reportHeaderLen + 6))
                {
                    return(null);
                }
            }
        }
Пример #3
0
        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);
                }
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        public Packet WritePacket(OpCodes op1, byte op2, Packet packet, byte op3 = 0)
        {
            lock (locker)
            {
                int    numPackets     = 1;
                int    offset         = 0;
                byte[] completeBuffer = null;
                if (packet != null)
                {
                    completeBuffer = packet.GetWrittenBuffer();
                    numPackets     = (completeBuffer.Length / 0x38) + 1;
                }

                bool allowsLongOffset = false;
                int  offsetOffset     = 2;
                int  lengthOffset     = 4;
                switch (op1)
                {
                case OpCodes.DriverLayerSetKeyValues:
                case OpCodes.DriverLayerUpdateRealtimeLighting:
                case OpCodes.LayerSetLightValues:
                    offsetOffset     = 2;
                    lengthOffset     = 5;
                    allowsLongOffset = true;
                    break;

                case OpCodes.LayerSetKeyPressLightingEffect:
                case OpCodes.LayerSetKeyValues:
                case OpCodes.LayerFnSetKeyValues:
                case OpCodes.LayerSetMacros:
                    offsetOffset = 2;
                    lengthOffset = 4;
                    break;
                }

                const int reportHeaderLen = 1;

                try
                {
                    for (int i = 0; i < numPackets; i++)
                    {
                        byte[] report = new byte[65];
                        report[1] = (byte)op1;
                        report[2] = op2;
                        if (op3 > 0)
                        {
                            // Not really an op, used for setting keyboard data buffers
                            report[3] = op3;
                        }
                        if (completeBuffer != null)
                        {
                            int numBytesToWrite = Math.Min(0x38, completeBuffer.Length - offset);
                            Buffer.BlockCopy(completeBuffer, offset, report, reportHeaderLen + 8, numBytesToWrite);
                            if (numPackets > 1)
                            {
                                report[reportHeaderLen + offsetOffset + 0] = (byte)offset;
                                report[reportHeaderLen + offsetOffset + 1] = (byte)(offset >> 8);
                                if (allowsLongOffset)
                                {
                                    report[reportHeaderLen + offsetOffset + 3] = (byte)(offset >> 16);
                                }
                                report[reportHeaderLen + lengthOffset] = (byte)numBytesToWrite;
                            }
                        }
                        Crc16.InsertCrc(report, reportHeaderLen, 6 + reportHeaderLen);
                        stream.Write(report);

                        byte[] resultBuffer = GetResponse((byte)op1, op2);
                        if (resultBuffer[0] != (byte)op1 /* || resultBuffer[1] != op2*/)
                        {
                            return(null);
                        }
                        if (!Crc16.ValidateCrc(resultBuffer))
                        {
                            return(null);
                        }
                        if (i == numPackets - 1)
                        {
                            Packet result = new Packet(true, resultBuffer);
                            result.Index    = 8;
                            lastSentMessage = Environment.TickCount;
                            return(result);
                        }
                        offset += 0x38;
                    }
                }
                catch
                {
                    return(null);
                }
                return(null);
            }
        }
Пример #6
0
        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);
            }
        }
Пример #7
0
        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;
            }
        }