private static byte[] DecryptMessage(ZWaveNode node, byte[] message, int start) { SecurityData nodeSecurityData = GetSecurityData(node); Utility.DebugLog(DebugMessageType.Information, "In DecryptMessage - SecurityHandler"); if (nodeSecurityData.ControllerNonceTimer.ElapsedMilliseconds > 10000) { Utility.DebugLog(DebugMessageType.Information, "Received the nonce too late'" + nodeSecurityData.ControllerNonceTimer.ElapsedMilliseconds + "' > 10000"); return(null); } // Utility.DebugLog(DebugMessageType.Information, "Message to be decrypted: " + BitConverter.ToString(message)); // Get IV from inbound packet byte[] iv = new byte[16]; Array.Copy(message, start + 1, iv, 0, 8); byte[] currentNonce = nodeSecurityData.GetControllerCurrentNonce(true); if (currentNonce == null) { Utility.DebugLog(DebugMessageType.Information, "currentNonce null"); return(null); } Utility.DebugLog(DebugMessageType.Information, "currentNonce NOT null"); Array.Copy(currentNonce, 0, iv, 8, 8); int _length = message.Length; int encryptedpackagesize = _length - 11 - 8; //19 + 11 + 8 byte[] encryptedpacket = new byte[encryptedpackagesize]; Array.Copy(message, 8 + start + 1, encryptedpacket, 0, encryptedpackagesize); byte[] decryptedpacket = AesWork.EncryptOfbMessage(nodeSecurityData.EncryptionKey, iv, encryptedpacket); Utility.DebugLog(DebugMessageType.Information, "Message " + BitConverter.ToString(message)); Utility.DebugLog(DebugMessageType.Information, "IV " + BitConverter.ToString(iv)); //Utility.DebugLog(DebugMessageType.Information, "Encrypted Packet " + BitConverter.ToString(encryptedpacket)); Utility.DebugLog(DebugMessageType.Information, "Decrypted Packet " + BitConverter.ToString(decryptedpacket)); byte[] mac = GenerateAuthentication(nodeSecurityData.AuthorizationKey, message, start, _length, node.Id, 0x01, iv); byte[] e_mac = new byte[8]; Array.Copy(message, start + 8 + encryptedpackagesize + 2, e_mac, 0, 8); if (!Enumerable.SequenceEqual(mac, e_mac)) { Utility.DebugLog(DebugMessageType.Information, "Computed mac " + BitConverter.ToString(mac) + " does not match the provider mac " + BitConverter.ToString(e_mac) + ". Dropping."); if (nodeSecurityData.SecurePayload.Count > 1) { RequestNonce(node); } return(null); } /* * if (decryptedpacket[1] == (byte)CommandClass.Security && 1 == 0) * { * byte[] msg = new byte[decryptedpacket.Length - 1]; * Array.Copy(decryptedpacket, 1, msg, 0, msg.Length); * * Utility.DebugLog(DebugMessageType.Information, "Processing Internally: " + BitConverter.ToString(msg)); * * } * else * { */ byte[] msg = new byte[decryptedpacket.Length - 2 + 8]; Array.Clear(msg, 0, 7); Array.Copy(decryptedpacket, 1, msg, 7, msg.Length - 7); msg[6] = (byte)(msg.Length - 7); Utility.DebugLog(DebugMessageType.Information, "Forwarding: " + BitConverter.ToString(msg)); /* send to the Command Class for Proecssing */ Utility.DebugLog(DebugMessageType.Information, "Received External Command Class: " + BitConverter.ToString(new byte[] { decryptedpacket[1] })); // node.MessageRequestHandler(node.pController, msg); Utility.DebugLog(DebugMessageType.Information, "In DecryptMessage - Finished"); return(msg); }
private static byte[] GenerateAuthentication(byte[] authorizationKey, byte[] data, int start, int length, byte sendingNode, byte receivingNode, byte[] iv) { // data should stat at 4 byte[] buffer = new byte[256]; byte[] tmpauth = new byte[16]; int ib = 0; buffer[ib] = data[start + 0]; ib++; buffer[ib] = sendingNode; ib++; buffer[ib] = receivingNode; ib++; buffer[ib] = (byte)(length - 19); Array.Copy(data, start + 9, buffer, 4, buffer[3]); byte[] buff = new byte[length - 19 + 4]; Array.Copy(buffer, buff, length - 19 + 4); // Utility.DebugLog(DebugMessageType.Information, "Raw Auth (minus IV)" + BitConverter.ToString(buff)); tmpauth = AesWork.EncryptEcbMessage(authorizationKey, iv); byte[] encpck = new byte[16]; Array.Clear(encpck, 0, 16); int block = 0; for (int i = 0; i < buff.Length; i++) { encpck[block] = buff[i]; block++; if (block == 16) { for (int j = 0; j < 16; j++) { tmpauth[j] = (byte)(encpck[j] ^ tmpauth[j]); encpck[j] = 0; } block = 0; tmpauth = AesWork.EncryptEcbMessage(authorizationKey, tmpauth); } } /* any left over data that isn't a full block size*/ if (block > 0) { for (int i = 0; i < 16; i++) { tmpauth[i] = (byte)(encpck[i] ^ tmpauth[i]); } tmpauth = AesWork.EncryptEcbMessage(authorizationKey, tmpauth); } byte[] auth = new byte[8]; Array.Copy(tmpauth, auth, 8); // Utility.DebugLog(DebugMessageType.Information, "Computed Auth " + BitConverter.ToString(auth)); return(auth); }
// IN the mesage to be Encrypted // OUT - true - message processed and sent - proceed to next one // - false - we need to wait for the nonce report to come private static bool EncryptMessage(ZWaveNode node, byte[] message) { SecurityData nodeSecurityData = GetSecurityData(node); Utility.DebugLog(DebugMessageType.Information, "In EncryptMessage - secure_payload [" + nodeSecurityData.SecurePayload.Count + "] - " + nodeSecurityData.DeviceNonceTimer.ElapsedMilliseconds); // if we get true we need to wait for the new Nonce // if we get false we need to proceed // if (sendRequestNonce()) // return false; if (nodeSecurityData.DeviceNonceTimer.ElapsedMilliseconds > 10000) { return(false); } SecutiryPayload payload = null; lock (nodeSecurityData.SecurePayload) { if (nodeSecurityData.SecurePayload.Count > 0) { payload = nodeSecurityData.SecurePayload.First(); nodeSecurityData.SecurePayload.Remove(payload); } } if (payload != null) { int len = payload.length + 20; byte[] t_message = new byte[len]; int i = 0; t_message[i] = (byte)CommandClass.Security; i++; t_message[i] = (byte)SecurityCommand.MessageEncap; byte[] initializationVector = new byte[16]; for (int a = 0; a < 8; a++) { initializationVector[a] = (byte)0xAA; i++; t_message[i] = initializationVector[a]; } Array.Copy(nodeSecurityData.DeviceCurrentNonce, 0, initializationVector, 8, 8); int sequence = 0; if (payload.part == 1) { ++nodeSecurityData.SequenceCounter; sequence = nodeSecurityData.SequenceCounter & (byte)0x0f; sequence |= (byte)0x10; } else if (payload.part == 2) { ++nodeSecurityData.SequenceCounter; sequence = nodeSecurityData.SequenceCounter & (byte)0x0f; sequence |= (byte)0x30; } byte[] plaintextmsg = new byte[payload.length + 1]; plaintextmsg[0] = (byte)sequence; for (int a = 0; a < payload.length; a++) { plaintextmsg[a + 1] = payload.message[a]; } byte[] encryptedPayload = new byte[30]; encryptedPayload = AesWork.EncryptOfbMessage(nodeSecurityData.EncryptionKey, initializationVector, plaintextmsg); Utility.DebugLog(DebugMessageType.Information, "authKey " + BitConverter.ToString(nodeSecurityData.AuthorizationKey)); Utility.DebugLog(DebugMessageType.Information, "EncryptKey " + BitConverter.ToString(nodeSecurityData.EncryptionKey)); Utility.DebugLog(DebugMessageType.Information, "Input Packet: " + BitConverter.ToString(plaintextmsg)); Utility.DebugLog(DebugMessageType.Information, "IV " + BitConverter.ToString(initializationVector)); Utility.DebugLog(DebugMessageType.Information, "encryptedPayload " + BitConverter.ToString(encryptedPayload)); for (int a = 0; a < payload.length + 1; ++a) { i++; t_message[i] = encryptedPayload[a]; } i++; t_message[i] = nodeSecurityData.DeviceCurrentNonce[0]; //GenerateAuthentication int start = 1; byte[] mac = GenerateAuthentication(nodeSecurityData.AuthorizationKey, t_message, start, t_message.Length + 2 - start - 1, 0x01, node.Id, initializationVector); for (int a = 0; a < 8; ++a) { i++; t_message[i] = mac[a]; } node.SendDataRequest(t_message); Utility.DebugLog(DebugMessageType.Information, "In EncryptMessage - message sent"); if ((nodeSecurityData.IsNetworkKeySet == false) && payload.message[0] == (byte)CommandClass.Security && payload.message[1] == (byte)SecurityCommand.NetworkKeySet) { nodeSecurityData.IsNetworkKeySet = true; nodeSecurityData.IsAddingNode = false; } return(true); } return(true); }