Exemple #1
0
        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);
        }
Exemple #2
0
 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)
 }
Exemple #3
0
 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);
        }
Exemple #5
0
        /// <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);
        }
Exemple #7
0
        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);
        }
Exemple #8
0
        //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);
        }
Exemple #9
0
        /// <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);
            }
        }
Exemple #10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Aes128Algorythm"/> class.
 /// </summary>
 public Aes128Algorythm()
 {
     Engine = new ZWaveAES();
 }