public static void Decrypt(ZWaveAES aesEngine, byte[] encKey, byte[] iv, ref byte[] payload) { string pre = payload.GetHex(); aesEngine.AES_OFB(encKey, iv, payload, false); string after = payload.GetHex(); "S0 {0} = {1}"._DLOG(after, pre); }
public static void LoadKeys(ZWaveAES aesEngine, byte[] networkKey, out byte[] authKey, out byte[] encKey) { authKey = new byte[16]; encKey = new byte[16]; byte[] pattern = ZWaveAES.RepeatByte16(0x55); aesEngine.AES_ECB(networkKey, pattern, authKey); // K_A = AES(K_N,pattern) pattern = ZWaveAES.RepeatByte16(0xAA); aesEngine.AES_ECB(networkKey, pattern, encKey); // K_E = AES(K_N,pattern) }
public static byte[] MakeAuthTag(ZWaveAES aesEngine, byte[] authKey, byte[] header, byte[] payload) { byte[] tempMAC = new byte[16]; aesEngine.AES_CBCMAC(authKey, header, payload, tempMAC); byte[] temp8bitMAC = new byte[8]; for (int i = 0; i < 8; i++) { temp8bitMAC[i] = tempMAC[i]; } //Tools._writeDebugDiagnosticMessage("****MAKE - AK:" + Tools.GetHex(authKey, "", false) + " header:" + Tools.GetHex(header, "", false) + " payload:" + Tools.GetHex(payload, "", false) + " code:" + Tools.GetHex(tempMAC, "", false)); return(temp8bitMAC); }
public static byte[] DecryptPayload(byte[] externalNonce, byte[] internalNonce, byte[] securityKey, byte[] message) { ZWaveAES AES = new ZWaveAES(); byte[] _authKey = new byte[16]; byte[] _encKey = new byte[16]; SecurityS0Utils.LoadKeys(AES, securityKey, out _authKey, out _encKey); byte[] _IV = new byte[16]; Array.Copy(internalNonce, 0, _IV, 0, internalNonce.Length); Array.Copy(externalNonce, 0, _IV, 8, externalNonce.Length); SecurityS0Utils.Decrypt(AES, _encKey, _IV, ref message); return(message); }
/// <summary> /// Decrypts the payload. /// </summary> /// <param name="networkKey">The network key.</param> /// <param name="encryptedPayload">The encrypted payload.</param> /// <param name="IV">The IV.</param> /// <returns></returns> public byte[] DecryptPayload(byte[] networkKey, byte[] encryptedPayload, byte[] IV) { try { ///////////////////////////// //byte[] authKey = new byte[16]; byte[] encKey = new byte[16]; //byte[] pattern = ZWaveAES.RepeatByte16(0x55); //AES.AES_ECB(authData.Key, pattern, authKey); // K_A = AES(K_N,pattern) byte[] pattern = ZWaveAES.RepeatByte16(0xAA); Engine.AES_ECB(networkKey, pattern, encKey); // K_E = AES(K_N,pattern) ///////////////////////////// byte[] output = new byte[0]; byte[] encPayload = new byte[0]; if (encryptedPayload.Length < 16) { output = ExpandEmptyArray(16); encPayload = ExpandEmptyArray(16); } else { output = ExpandEmptyArray(encryptedPayload.Length); encPayload = ExpandEmptyArray(encryptedPayload.Length); } for (int i = 0; i < encryptedPayload.Length; i++) { encPayload[i] = encryptedPayload[i]; } Engine.AES_OFB(encKey, IV, encPayload, true); byte[] decryptedPayload = new byte[encryptedPayload.Length]; for (int i = 0; i < encryptedPayload.Length; i++) { if (i < encPayload.Length) { decryptedPayload[i] = encPayload[i]; } } return(decryptedPayload); } catch (Exception ex) { throw new ApplicationException("SecurityException", ex); } }
public static byte[] EncryptCommand(byte property, byte[] command, byte senderNodeId, byte receiverNodeId, byte[] internalNonce, byte[] externalNonce, byte[] networkKey, bool isWithNonceGet) { byte[] _authKey = new byte[16]; byte[] _encKey = new byte[16]; COMMAND_CLASS_SECURITY.SECURITY_MESSAGE_ENCAPSULATION.Tproperties1 prop = property; COMMAND_CLASS_SECURITY.SECURITY_MESSAGE_ENCAPSULATION ret = new COMMAND_CLASS_SECURITY.SECURITY_MESSAGE_ENCAPSULATION(); ret.initializationVectorByte = internalNonce; byte[] payload = new byte[command.Length + 1]; payload[0] = prop; Array.Copy(command, 0, payload, 1, command.Length); byte[] IV = new byte[16]; Array.Copy(internalNonce, 0, IV, 0, 8); Array.Copy(externalNonce, 0, IV, 8, 8); ZWaveAES _aesEngine = new ZWaveAES(); SecurityS0Utils.LoadKeys(_aesEngine, networkKey, out _authKey, out _encKey); SecurityS0Utils.Encrypt(_aesEngine, _encKey, IV, ref payload); ret.properties1 = payload[0]; if (payload.Length > 0) { ret.commandByte = new List <byte>(); for (int i = 1; i < payload.Length; i++) { ret.commandByte.Add(payload[i]); } } ret.receiversNonceIdentifier = externalNonce[0]; byte[] header = new byte[20]; Array.Copy(IV, 0, header, 0, IV.Length); header[16] = COMMAND_CLASS_SECURITY.SECURITY_MESSAGE_ENCAPSULATION.ID; if (isWithNonceGet) { header[16] = COMMAND_CLASS_SECURITY.SECURITY_MESSAGE_ENCAPSULATION_NONCE_GET.ID; } else { header[16] = COMMAND_CLASS_SECURITY.SECURITY_MESSAGE_ENCAPSULATION.ID; } header[17] = senderNodeId; header[18] = receiverNodeId; header[19] = (byte)payload.Length; ret.messageAuthenticationCodeByte = SecurityS0Utils.MakeAuthTag(_aesEngine, _authKey, header, payload); return(ret); }
public static bool VerifyAuthTag(ZWaveAES aesEngine, byte[] authKey, byte[] header, byte[] payload, byte[] remoteMAC) { // Calculate actual MAC byte[] localMAC = new byte[16]; aesEngine.AES_CBCMAC(authKey, header, payload, localMAC); byte[] local8bitMAC = new byte[8]; for (int i = 0; i < 8; i++) { local8bitMAC[i] = localMAC[i]; } bool ret = Tools.ByteArrayEquals(local8bitMAC, remoteMAC); //Tools._writeDebugDiagnosticMessage("****VERF - AK:" + Tools.GetHex(authKey, "", false) + " header:" + Tools.GetHex(header, "", false) + " payload:" + Tools.GetHex(payload, "", false) + " code:" + Tools.GetHex(localMAC, "", false) + " remote:" + Tools.GetHex(remoteMAC, "", false)); return(ret); }
//private IApplicationLayer zwApplicationLayer; /// <summary> /// Initializes a new instance of the <see cref="ZWavePRNG"/> class. /// /// The ZWavePRNG is based on a seed which should be provided from a hardware source /// eg. a ZWave Module. /// The seed is then fed into the chosen Encryption method, it is up to the implementor to /// ensure that the chosen encryption method is suitable for generating pseudo random numbers, /// which AES is considered to be. /// /// Implementation specifics: /// /// State Initialisation (SDS10865 cp. 5.4.1): /// ------------------------------------------ /// The inner state is initialized up including the node into the network and after SRAM loss /// 1. Set the inner state to zero /// 2. Run the state update function /// /// State Update (SDS10865 cp. 5.4.2): /// ---------------------------------- /// 1. Get 128 bits of fresh unput H2 as follow: /// a. Collect 256 bit (32 byte) of data from the hardware generator /// b. Split these bits into the 128-bit encoded keys doneted K1 and K2, and set H0 to be the value 0xA5 (repeated 16 times). /// c. Compute H1 = AES(K1; H0) XOR H0 /// d. Compute H2 = AES(K2; H1) XOR H1 /// 2. Compute S = Inner State XOR H2 /// 3. Use S as AES key and encrypt the value 0x36 (repeated 16 time). /// 4. Store the result as the inner state in SRAM, and make sure to delete the old inner state all intermediate values. /// /// Output Generation (SDS10865 cp. 5.4.3): /// --------------------------------------- /// Every time that k bits (k STE 128) of output are requested from the PRNG, the following steps are followed: /// 1. Use the current inner state as AES key. /// 2. Encrypt the value 0x5C (repeated 16 times) and use the least significant k bits of the result as PRNG output /// 3. Encrypt the value 0x36 (repeated 16 times) and store the result as the new inner state in SRAM. /// Make sure to delete the old inner state and all intermediate values. /// /// /// </summary> public ZWavePRNG(byte[] randomResult) { AESEngine = new ZWaveAES(); K1 = new byte[16]; K2 = new byte[16]; H0 = new byte[16]; H1 = new byte[16]; H2 = new byte[16]; // State Initialisation // 1. Zero innerState innerState = new byte[16]; //this.zwApplicationLayer = zwApplicationLayer; // 2. Call StateUpdate PRNGUpdate(randomResult); }
/// <summary> /// Authenticates the specified network key. /// </summary> /// <param name="networkKey">The network key.</param> /// <param name="noncesPayload">The nonces payload.</param> /// <param name="framePayload">The frame payload.</param> /// <param name="commandClassKey">The command class key.</param> /// <param name="sourceId">The source id.</param> /// <param name="destId">The dest id.</param> /// <returns></returns> public AuthData Authenticate(byte[] networkKey, byte[] noncesPayload, byte[] framePayload, byte commandClassKey, byte sourceId, byte destId) { try { AuthData authData = new AuthData(networkKey); if (noncesPayload.Length > 9 && framePayload.Length > framePayload.Length - 9 && framePayload.Length > 19) { authData.Nonces = new byte[] { noncesPayload[2], noncesPayload[3], noncesPayload[4], noncesPayload[5], noncesPayload[6], noncesPayload[7], noncesPayload[8], noncesPayload[9] }; authData.RI = framePayload[framePayload.Length - 9]; authData.MAC = new byte[] { framePayload[framePayload.Length - 8], framePayload[framePayload.Length - 7], framePayload[framePayload.Length - 6], framePayload[framePayload.Length - 5], framePayload[framePayload.Length - 4], framePayload[framePayload.Length - 3], framePayload[framePayload.Length - 2], framePayload[framePayload.Length - 1] }; authData.IV = new byte[] { framePayload[2], framePayload[3], framePayload[4], framePayload[5], framePayload[6], framePayload[7], framePayload[8], framePayload[9] }; authData.EncryptedPayload = new byte[framePayload.Length - 19]; int index = 0; for (int i = 10; i < framePayload.Length - 9; i++) { authData.EncryptedPayload[index] = framePayload[i]; index++; } ZWaveAES AES = new ZWaveAES(); byte[] tempMAC = new byte[16]; byte[] authKey = new byte[16]; byte[] encKey = new byte[16]; byte[] pattern = ZWaveAES.RepeatByte16(0x55); AES.AES_ECB(authData.Key, pattern, authKey); // K_A = AES(K_N,pattern) pattern = ZWaveAES.RepeatByte16(0xAA); AES.AES_ECB(authData.Key, pattern, encKey); // K_E = AES(K_N,pattern) authData.SecurityAuthData = new ZWaveSecurityAuthData(authData.IV, authData.Nonces, commandClassKey, sourceId, destId, (byte)authData.EncryptedPayload.Length); AES.AES_CBCMAC(authKey, authData.SecurityAuthData.ToByteArray(), authData.EncryptedPayload, tempMAC); authData.IsValid = true; for (int i = 0; i < 8; i++) { if (tempMAC[i] != authData.MAC[i]) { authData.IsValid = false; break; } } } return(authData); } catch (Exception ex) { throw new ApplicationException("SecurityException", ex); } }
/// <summary> /// Initializes a new instance of the <see cref="Aes128Algorythm"/> class. /// </summary> public Aes128Algorythm() { Engine = new ZWaveAES(); }