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) }
/// <summary> /// Called: When fresh input from hardware RNG is needed /// Task: Update the PRNG with data from hardware RNG /// Global vars: prngState[0..15] Modify /// Temp data: byt k[16], h[16], temp[16], i, j /// </summary> public void PRNGUpdate(byte[] randomResult) { byte[] hwData; // 1.a. Collect 256 bit (32 byte) data from hw generator hwData = GetHWRNG(32, randomResult); // 1.b. for (int i = 0; i < hwData.Length; i++) { if (i < 16) { K1[i] = hwData[i]; } else { K2[i - 16] = hwData[i]; } } H0 = new byte[] { 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5 }; // 1.c. AESEngine.AES_ECB(K1, H0, H1); for (int i = 0; i < H1.Length; i++) { H1[i] ^= H0[i]; } // 1.d. AESEngine.AES_ECB(K2, H1, H2); for (int i = 0; i < H2.Length; i++) { H2[i] ^= H1[i]; } // 2. byte[] S = new byte[16]; for (int i = 0; i < innerState.Length; i++) { S[i] = (byte)(innerState[i] ^ H2[i]); } // 3 + 4. byte[] ISGen = { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 }; innerState = new byte[16]; AESEngine.AES_ECB(S, ISGen, innerState); }
/// <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); } }
/// <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); } }