Exemple #1
0
        /// <summary>
        /// Create a RC4 decryptor
        /// </summary>
        /// <param name="key">the key</param>
        /// <returns>the RC4 decryptor</returns>
        internal static ICryptoTransform CreateRc4Decryptor(byte[] key)
        {
            // check input
            if (null == key)
            {
                throw new ArgumentNullException("key");
            }

            // CryptoLib RC4 needs no initial vector
            RC4CryptoServiceProvider rc4 = new RC4CryptoServiceProvider();

            return(rc4.CreateDecryptor(key, null));
        }
        /// <summary>
        /// Encrypts input data with RC4
        /// </summary>
        /// <param name="input">The input data to be encrypted</param>
        /// <param name="inputOffset">Offset of input from which the data will be encrypted </param>
        /// <param name="inputLength">Length of data to be encrypted</param>
        /// <param name="key">The encryption key</param>
        private static byte[] RC4Encrypt(byte[] input, int inputOffset, int inputLength, byte[] key)
        {
            RC4CryptoServiceProvider rc4 = new RC4CryptoServiceProvider();
            ICryptoTransform crypto = rc4.CreateEncryptor(key, null);
            byte[] output = crypto.TransformFinalBlock(input, inputOffset, inputLength);

            return output;
        }
        /// <summary>
        /// Update session key according to section 5.3.7 Session Key Updates.
        /// </summary>
        internal void UpdateSessionKey()
        {
            if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT
                || encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT
                || encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT)
            {
                currentClientEncryptKey = UpdateKey(initialClientEncryptKey,
                                                    currentClientEncryptKey,
                                                    encryptionMethod);

                currentClientDecryptKey = UpdateKey(initialClientDecryptKey,
                                                    currentClientDecryptKey,
                                                    encryptionMethod);

                currentServerEncryptKey = UpdateKey(initialServerEncryptKey,
                                                    currentServerEncryptKey,
                                                    encryptionMethod);

                currentServerDecryptKey = UpdateKey(initialServerDecryptKey,
                                                    currentServerDecryptKey,
                                                    encryptionMethod);

                RC4CryptoServiceProvider rc4Enc = new RC4CryptoServiceProvider();
                rc4Encrypt = rc4Enc.CreateEncryptor(currentClientEncryptKey, null);
                rc4EncryptServer = rc4Enc.CreateEncryptor(currentServerEncryptKey, null);

                RC4CryptoServiceProvider rc4Dec = new RC4CryptoServiceProvider();
                rc4Decrypt = rc4Dec.CreateDecryptor(currentClientDecryptKey, null);
                rc4DecryptServer = rc4Dec.CreateDecryptor(currentServerDecryptKey, null);
            }
            // else in other cases we don't need to update session key
        }
        /// <summary>
        /// Update session key for Non-FIPS according to section 5.3.7 Session Key Updates.
        /// </summary>
        /// <param name="initialKey">The initial session key.</param>
        /// <param name="currentKey">The current session key.</param>
        /// <param name="encryptionMethod">The current encryption method.</param>
        /// <returns>The new session key.</returns>
        private static byte[] UpdateKey(byte[] initialKey, byte[] currentKey, EncryptionMethods encryptionMethod)
        {
            byte[] pad1 = ConstValue.NON_FIPS_PAD1;
            byte[] pad2 = ConstValue.NON_FIPS_PAD2;
            byte[] newKey = null;

            // SHAComponent = SHA(InitialEncryptKey + Pad1 + CurrentEncryptKey)
            byte[] shaComponentBuffer = RdpbcgrUtility.ConcatenateArrays(initialKey, pad1, currentKey);
            byte[] shaComponent = ShaHash(shaComponentBuffer);

            // TempKey128 = MD5(InitialEncryptKey + Pad2 + SHAComponent)
            byte[] tempKey128Buffer = RdpbcgrUtility.ConcatenateArrays(initialKey, pad2, shaComponent);
            byte[] tempKey128 = MD5Hash(tempKey128Buffer);

            if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT)
            {
                // S-TableEncrypt = InitRC4(TempKey128)
                RC4CryptoServiceProvider rc4 = new RC4CryptoServiceProvider();
                ICryptoTransform ict = rc4.CreateEncryptor(tempKey128, null);

                // NewEncryptKey128 = RC4(TempKey128, S-TableEncrypt)
                newKey = ict.TransformFinalBlock(tempKey128, 0, tempKey128.Length);
            }
            else if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT
                     || encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT)
            {
                // TempKey64 = First64Bits(TempKey128)
                byte[] tempKey64 = GetFirstNBits(64, tempKey128);

                // S-TableEncrypt = InitRC4(TempKey64)
                RC4CryptoServiceProvider rc4 = new RC4CryptoServiceProvider();
                ICryptoTransform ict = rc4.CreateEncryptor(tempKey64, null);

                // PreSaltKey = RC4(TempKey64, S-TableEncrypt)
                byte[] preSaltKey = ict.TransformFinalBlock(tempKey64, 0, tempKey64.Length);

                if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT)
                {
                    // NewEncryptKey40 = 0xD1269E + Last40Bits(PreSaltKey)
                    newKey = RdpbcgrUtility.ConcatenateArrays(ConstValue.NON_FIPS_SALT_40BIT, GetLastNBits(40, preSaltKey));
                }
                else
                {
                    // NewEncryptKey56 = 0xD1 + Last56Bits(PreSaltKey)
                    newKey = RdpbcgrUtility.ConcatenateArrays(ConstValue.NON_FIPS_SALT_56BIT, GetLastNBits(56, preSaltKey));
                }
            }
            // else do nothing

            return newKey;
        }
        internal void GenerateSessionKey(byte[] clientRandom, byte[] serverRandom)
        {
            if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT
                || encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT
                || encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT)
            {
                byte[] mackey = null;
                byte[] clientEncKey = null;
                byte[] clientDecKey = null;

                GenerateNonFIPSSessionKey(clientRandom, serverRandom, out mackey, out clientEncKey, out clientDecKey);
                if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_40BIT)
                {
                    // MACKey40 = 0xD1269E + Last40Bits(First64Bits(MACKey128))
                    byte[] salt = ConstValue.NON_FIPS_SALT_40BIT;
                    byte[] first = GetFirstNBits(64, mackey);
                    byte[] last = GetLastNBits(40, first);
                    macKey = RdpbcgrUtility.ConcatenateArrays(salt, last);

                    // InitialClientEncryptKey40 = 0xD1269E + Last40Bits(First64Bits(InitialClientEncryptKey128))
                    first = GetFirstNBits(64, clientEncKey);
                    last = GetLastNBits(40, first);
                    currentClientEncryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                    currentServerDecryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);

                    // InitialClientDecryptKey40 = 0xD1269E + Last40Bits(First64Bits(InitialClientDecryptKey128))
                    first = GetFirstNBits(64, clientDecKey);
                    last = GetLastNBits(40, first);
                    currentClientDecryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                    currentServerEncryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                }
                else if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_56BIT)
                {
                    // MACKey56 = 0xD1 + Last56Bits(First64Bits(MACKey128))
                    byte[] salt = ConstValue.NON_FIPS_SALT_56BIT;
                    byte[] first = GetFirstNBits(64, mackey);
                    byte[] last = GetLastNBits(56, first);
                    macKey = RdpbcgrUtility.ConcatenateArrays(salt, last);

                    // InitialClientEncryptKey56 = 0xD1 + Last56Bits(First64Bits(InitialClientEncryptKey128))
                    first = GetFirstNBits(64, clientEncKey);
                    last = GetLastNBits(56, first);
                    currentClientEncryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                    currentServerDecryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);

                    // InitialClientDecryptKey56 = 0xD1 + Last56Bits(First64Bits(InitialClientDecryptKey128))
                    first = GetFirstNBits(64, clientDecKey);
                    last = GetLastNBits(56, first);
                    currentClientDecryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                    currentServerEncryptKey = RdpbcgrUtility.ConcatenateArrays(salt, last);
                }
                else // encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_128BIT
                {
                    macKey = mackey;
                    currentClientEncryptKey = clientEncKey;
                    currentServerDecryptKey = clientEncKey;
                    currentClientDecryptKey = clientDecKey;
                    currentServerEncryptKey = clientDecKey;
                }

                initialClientDecryptKey = currentClientDecryptKey;
                initialClientEncryptKey = currentClientEncryptKey;
                initialServerEncryptKey = currentServerEncryptKey;
                initialServerDecryptKey = currentServerDecryptKey;
                RC4CryptoServiceProvider rc4Enc = new RC4CryptoServiceProvider();
                rc4Encrypt = rc4Enc.CreateEncryptor(currentClientEncryptKey, null);
                rc4EncryptServer = rc4Enc.CreateEncryptor(currentServerEncryptKey, null);
                RC4CryptoServiceProvider rc4Dec = new RC4CryptoServiceProvider();
                rc4Decrypt = rc4Dec.CreateDecryptor(currentClientDecryptKey, null);
                rc4DecryptServer = rc4Dec.CreateDecryptor(currentServerDecryptKey, null);
            }
            else if (encryptionMethod == EncryptionMethods.ENCRYPTION_METHOD_FIPS)
            {
                GenerateFIPSSessionKey(clientRandom, serverRandom, out macKey,
                                       out currentClientEncryptKey, out currentClientDecryptKey,
                                       out currentServerEncryptKey, out currentServerDecryptKey);
                initialClientDecryptKey = currentClientDecryptKey;
                initialClientEncryptKey = currentClientEncryptKey;
                initialServerDecryptKey = currentServerDecryptKey;
                initialServerEncryptKey = currentServerEncryptKey;

                // suppress "CA5353:TripleDESCannotBeUsed" message, since TripleDES is used according protocol definition in MS-RDPBCGR
                desEncrypt = new TripleDESCryptoServiceProvider();
                desEncrypt.IV = ConstValue.TRPLE_DES_IV;
                desEncrypt.Key = currentClientEncryptKey;
                desEncrypt.Mode = CipherMode.CBC;

                desDecrypt = new TripleDESCryptoServiceProvider();
                desDecrypt.IV = ConstValue.TRPLE_DES_IV;
                desDecrypt.Key = currentClientDecryptKey;
                desDecrypt.Mode = CipherMode.CBC;

                desEncryptServer = new TripleDESCryptoServiceProvider();
                desEncryptServer.IV = ConstValue.TRPLE_DES_IV;
                desEncryptServer.Key = currentServerEncryptKey;
                desEncryptServer.Mode = CipherMode.CBC;

                desDecryptServer = new TripleDESCryptoServiceProvider();
                desDecryptServer.IV = ConstValue.TRPLE_DES_IV;
                desDecryptServer.Key = currentServerDecryptKey;
                desDecryptServer.Mode = CipherMode.CBC;
            }
            else  // the encryption method is ENCRYPTION_METHOD_NONE or error
            {
                macKey = null;
                initialClientEncryptKey = null;
                initialClientDecryptKey = null;
                currentClientEncryptKey = null;
                currentClientDecryptKey = null;
                initialServerEncryptKey = null;
                initialServerDecryptKey = null;
                currentServerEncryptKey = null;
                currentServerDecryptKey = null;
                rc4Encrypt = null;
                rc4Decrypt = null;
                rc4EncryptServer = null;
                rc4DecryptServer = null;
                desEncrypt = null;
                desDecrypt = null;
                desEncryptServer = null;
                desDecryptServer = null;
            }

            // the cumulative encryption/decryption count
            // indicating how many encryptions/decryptions have been carried out.
            encryptionCount = 0;  // the first encryption start with 0
            decryptionCount = -1; // after the first decryption, decryptionCount++ up to 0
        }