public async Task InvalidPathToEncrypt()
        {
            TestDoc           testDoc = TestDoc.Create();
            EncryptionOptions encryptionOptionsWithInvalidPathToEncrypt = new EncryptionOptions()
            {
                DataEncryptionKeyId = LegacyEncryptionProcessorTests.dekId,
                EncryptionAlgorithm = CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized,
                PathsToEncrypt      = new List <string>()
                {
                    "/SensitiveStr", "/Invalid"
                }
            };

            Stream encryptedStream = await EncryptionProcessor.EncryptAsync(
                testDoc.ToStream(),
                LegacyEncryptionProcessorTests.mockEncryptor.Object,
                encryptionOptionsWithInvalidPathToEncrypt,
                new CosmosDiagnosticsContext(),
                CancellationToken.None);

            JObject encryptedDoc = EncryptionProcessor.BaseSerializer.FromStream <JObject>(encryptedStream);

            (JObject decryptedDoc, DecryptionContext decryptionContext) = await EncryptionProcessor.DecryptAsync(
                encryptedDoc,
                LegacyEncryptionProcessorTests.mockEncryptor.Object,
                new CosmosDiagnosticsContext(),
                CancellationToken.None);

            LegacyEncryptionProcessorTests.VerifyDecryptionSucceeded(
                decryptedDoc,
                testDoc,
                1,
                decryptionContext,
                invalidPathsConfigured: true);
        }
Exemple #2
0
 /// <summary>
 /// Run the Cipher on a collection of data
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="modelList"></param>
 /// <param name="encryptionOption"></param>
 public IEnumerable <T> RunCipher <T>(IEnumerable <T> modelList, EncryptionOptions encryptionOption)
 {
     foreach (var model in modelList)
     {
         yield return(RunCipher(model, encryptionOption));
     }
 }
Exemple #3
0
        private SNILoadHandle() : base(IntPtr.Zero, true)
        {
            // From security review - SafeHandle guarantees this is only called once.
            // The reason for the safehandle is guaranteed initialization and termination of SNI to
            // ensure SNI terminates and cleans up properly.
            try
            { }
            finally
            {
                _sniStatus = SNINativeMethodWrapper.SNIInitialize();

                uint value = 0;

                // VSDevDiv 479597: If initialize fails, don't call QueryInfo.
                if (TdsEnums.SNI_SUCCESS == _sniStatus)
                {
                    // Query OS to find out whether encryption is supported.
                    SNINativeMethodWrapper.SNIQueryInfo(SNINativeMethodWrapper.QTypes.SNI_QUERY_CLIENT_ENCRYPT_POSSIBLE, ref value);
                }

                _encryptionOption = (value == 0) ? EncryptionOptions.NOT_SUP : EncryptionOptions.OFF;

                base.handle = (IntPtr)1; // Initialize to non-zero dummy variable.
            }
        }
Exemple #4
0
        public static CipherResult BinaryEncryptWithStaticIv(byte[] fileToEncrypt, string passPhrase,
                                                             EncryptionOptions eO = null)
        {
            var cipherObject = BasicAesEncryption(fileToEncrypt, passPhrase, eO);

            return(cipherObject);
        }
Exemple #5
0
        protected SymmetricEncryption(
            EncryptionOptions options,
            TSymmetricAlgorithm symmetricAlgorithm,
            Func <string, byte[], int, DeriveBytes> deriveBytesFactory,
            string password) : base(options, password)
        {
            if (symmetricAlgorithm == null)
            {
                throw new ArgumentNullException("symmetricAlgorithm");
            }

            if (deriveBytesFactory == null)
            {
                throw new ArgumentNullException("deriveBytesFactory");
            }

            SymmetricAlgorithm = symmetricAlgorithm;

            int keySizeBytes   = SymmetricAlgorithm.KeySize / 8;
            int blockSizeBytes = SymmetricAlgorithm.BlockSize / 8;

            DeriveBytes passwordDeriveBytes = deriveBytesFactory(password, options.Salt, options.IterationCount);

            SymmetricAlgorithm.Key = passwordDeriveBytes.GetBytes(keySizeBytes);

            DeriveBytes ivDeriveBytes = deriveBytesFactory(options.IvBase, new byte[8], 1);

            SymmetricAlgorithm.IV = ivDeriveBytes.GetBytes(blockSizeBytes);
        }
Exemple #6
0
        public async Task InvalidPathToEncrypt()
        {
            TestDoc           testDoc = TestDoc.Create();
            EncryptionOptions encryptionOptionsWithInvalidPathToEncrypt = new EncryptionOptions()
            {
                DataEncryptionKeyId = EncryptionProcessorTests.dekId,
                EncryptionAlgorithm = CosmosEncryptionAlgorithm.AEAes256CbcHmacSha256Randomized,
                PathsToEncrypt      = new List <string>()
                {
                    "/SensitiveStr", "/Invalid"
                }
            };

            try
            {
                await EncryptionProcessor.EncryptAsync(
                    testDoc.ToStream(),
                    EncryptionProcessorTests.mockEncryptor.Object,
                    encryptionOptionsWithInvalidPathToEncrypt,
                    new CosmosDiagnosticsContext(),
                    CancellationToken.None);

                Assert.Fail("Invalid path to encrypt didn't result in exception.");
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("PathsToEncrypt includes a path: '/Invalid' which was not found.", ex.Message);
            }
        }
Exemple #7
0
        public static EncryptionOptions ParseConnect(this TdsPackageReader reader, EncryptionOptions encryptionRequested)
        {
            var result = ParsePreLoginHandshake(reader.ReadBuffer, TdsEnums.HEADER_LEN, encryptionRequested);

            reader.PackageDone();
            return(result);
        }
        protected override Task <ChunkInfo> DeserializeBytesAsync(BinaryReader reader)
        {
            var  chunkType       = (StructureType)reader.ReadByte();
            long processedLength = reader.ReadInt64();
            CompressionOptions compressionOptions = null;
            EncryptionOptions  encryptionOptions  = null;

            bool isCompressed = reader.ReadBoolean();

            if (isCompressed)
            {
                compressionOptions = new CompressionOptions(
                    (CompressionType)reader.ReadByte(),
                    (CompressionLevel)reader.ReadByte());
            }

            bool isEncrypted = reader.ReadBoolean();

            if (isEncrypted)
            {
                byte[] readBytes = reader.ReadBytes(reader.ReadInt32());
                encryptionOptions = new EncryptionOptions(
                    algorithm: (EncryptionType)reader.ReadByte(),
                    ivBase: reader.ReadString(),
                    iterationCount: reader.ReadInt32(),
                    salt: readBytes);
            }

            return(Task.FromResult(new ChunkInfo(chunkType, encryptionOptions, compressionOptions, processedLength)));
        }
Exemple #9
0
        public void Update(IDictionary <string, T> values, byte[] password, EncryptionOptions options, ushort saltSize, int iterations)
        {
            var unsavedKeys = values.Keys.Except(ResolveKeys(password, iterations)).ToArray();

            if (unsavedKeys.Length != 0)
            {
                throw Error.Argument($@"Elements with these keys does not exist: 

{string.Join(Environment.NewLine, unsavedKeys)}");
            }

            var dictionary = Decrypt(password, iterations);
            var original   = dictionary.Values.ToArray();

            foreach (var kvp in values)
            {
                dictionary[kvp.Key] = kvp.Value;
            }

            Encrypt(dictionary, password, options, saltSize, iterations);

            if (typeof(IDisposable).IsAssignableFrom(typeof(T)))
            {
                //Clean up decrypted keys, make user clean up their own.
                foreach (var disposable in original.OfType <IDisposable>())
                {
                    disposable.Dispose();
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="SymmetricTransformer{T}"/> class
        /// using a given <see cref="SymmetricAlgorithm"/> instance.
        /// </summary>
        /// <param name="algorithm">
        /// An instance of <see cref="SymmetricAlgorithm"/>
        /// to use for encryption or decryption.
        /// Beware of side effect: The values
        /// of its <see cref="SymmetricAlgorithm.Key"/>
        /// and <see cref="SymmetricAlgorithm.IV"/>
        /// properties will be changed.
        /// </param>
        /// <param name="isEncryptor"></param>
        /// <param name="encryptionKey"></param>
        /// <param name="initializationVector"></param>
        /// <param name="options"></param>
        /// <remarks>
        /// <para>
        /// This is <em>not a pure method</em>, so beware of this side effect:
        /// When the given <see cref="SymmetricAlgorithm"/>
        /// instance is passed to this constructor, the values
        /// of its <see cref="SymmetricAlgorithm.Key"/>
        /// and <see cref="SymmetricAlgorithm.IV"/>
        /// properties will be changed by code inside
        /// this constructor.
        /// </para>
        /// <para>
        /// Also note that the instance of <see cref="SymmetricAlgorithm"/>
        /// will not be disposed when this transformer object's
        /// <see cref="Dispose"/> method is invoked, so the
        /// same algorithm object may be re-used later, and its
        /// creator assumes responsibility to dispose of it.
        /// </para>
        /// </remarks>
        protected SymmetricTransformer(
            [NotNull] T algorithm,
            bool isEncryptor,
            [NotNull] byte[] encryptionKey,
            byte[] initializationVector,
            EncryptionOptions options)
            : this(isEncryptor, encryptionKey, initializationVector, options)
        {
            Contract.Requires <ArgumentNullException>(algorithm != null);
            Contract.Requires <ArgumentNullException>(encryptionKey != null);

            ValidateKeySize(algorithm, encryptionKey);

            this.algorithm         = algorithm;
            this.algorithm.Key     = this.encryptionKey;
            this.preserveAlgorithm = true;

            if (this.initializationVector == null)
            {
                // Always generate a new vector
                // to use for the data to be
                // encrypted by this instance.
                this.algorithm.GenerateIV();
                this.initializationVector = this.algorithm.IV;
            }
            else
            {
                ValidateBlockSize(this.algorithm, this.initializationVector);

                this.algorithm.IV = this.initializationVector;
            }
        }
Exemple #11
0
        public static byte[] GetOnlyHashBytes(byte[] password, EncryptionOptions sO)
        {
            var bytes = SCrypt.ComputeDerivedKey(password, sO.Salt, sO.Cost, sO.BlockSize, sO.Parallel, null, sO.KeySizeInBytes);

            //return Convert.ToBase64String(bytes);
            return(bytes);
        }
Exemple #12
0
        public async Task DuplicatePathToEncrypt()
        {
            TestDoc           testDoc = TestDoc.Create();
            EncryptionOptions encryptionOptionsWithDuplicatePathToEncrypt = new EncryptionOptions()
            {
                DataEncryptionKeyId = MdeEncryptionProcessorTests.dekId,
                EncryptionAlgorithm = CosmosEncryptionAlgorithm.MdeAeadAes256CbcHmac256Randomized,
                PathsToEncrypt      = new List <string>()
                {
                    "/SensitiveStr", "/SensitiveStr"
                }
            };

            try
            {
                await EncryptionProcessor.EncryptAsync(
                    testDoc.ToStream(),
                    MdeEncryptionProcessorTests.mockEncryptor.Object,
                    encryptionOptionsWithDuplicatePathToEncrypt,
                    new CosmosDiagnosticsContext(),
                    CancellationToken.None);

                Assert.Fail("Duplicate paths in PathToEncrypt didn't result in exception.");
            }
            catch (InvalidOperationException ex)
            {
                Assert.AreEqual("Duplicate paths in PathsToEncrypt passed via EncryptionOptions.", ex.Message);
            }
        }
 public byte[] Encrypt(string key, T value, byte[] password, EncryptionOptions options, ushort saltSize, int iterations)
 {
     using (var stream = new MemoryStream())
     {
         ushort keyLength, encryptedLength;
         Encrypt(stream, key, value, password, options, saltSize, iterations, out keyLength, out encryptedLength);
         return(stream.ToArray());
     }
 }
 public ChunkInfo(
     StructureType type,
     EncryptionOptions encryptionOptions,
     CompressionOptions compressionOptions,
     long processedLength)
     : base(type, encryptionOptions, compressionOptions)
 {
     _processedLength = processedLength;
 }
Exemple #15
0
 public EtlOptions(ArchiveOptions archiveOptions, EncryptionOptions encryptionOptions, LoggingOptions loggingOptions, MoveOptions moveOptions, MoveDbOptions moveDbOptions, WatcherOptions watcherOptions)
 {
     ArchiveOptions    = archiveOptions;
     EncryptionOptions = encryptionOptions;
     LoggingOptions    = loggingOptions;
     MoveOptions       = moveOptions;
     MoveDbOptions     = moveDbOptions;
     WatcherOptions    = watcherOptions;
 }
Exemple #16
0
 public IConnectionBuilder Encryption(EncryptionOptions Encryption)
 {
     if (this.IsLocked == true)
     {
         throw new BuilderLockedException(this.GetType().FullName);
     }
     this.e_Encryption = Encryption;
     return(this);
 }
Exemple #17
0
        private void Created(object sender, FileSystemEventArgs e)
        {
            string   pathToFile = e.FullPath;
            DateTime date       = File.GetLastWriteTime(pathToFile);
            string   name       = Path.GetFileNameWithoutExtension(pathToFile);
            string   extansion  = Path.GetExtension(pathToFile);

            EncryptionOptions encryptionOptions =
                optionsManager.GetOptions <EncryptionOptions>() as EncryptionOptions;
            ArchivationOptions archivationOptions =
                optionsManager.GetOptions <ArchivationOptions>() as ArchivationOptions;


            if (extansion != ".gz" && extansion != "")
            {
                byte[] key, iv;
                (key, iv) = Encryption.GenKeyIv();

                if (encryptionOptions.NeedToEncrypt)
                {
                    File.WriteAllBytes(pathToFile, Encryption.Encrypt(pathToFile, key, iv));
                }

                string pathToArchive = Path.Combine(source, name + ".gz");
                Archivation.Compress(pathToFile, pathToArchive, archivationOptions);


                File.Delete(pathToFile);

                if (!Directory.Exists(saveArchive))
                {
                    Directory.CreateDirectory(saveArchive);
                }

                string newPathToArchive = Path.Combine(saveArchive, name + ".gz");
                if (File.Exists(newPathToArchive))
                {
                    File.Delete(newPathToArchive);
                }
                File.Move(pathToArchive, newPathToArchive);


                string newPathToFile = Path.Combine(target, date.Year.ToString(),
                                                    date.Month.ToString(), date.Day.ToString());
                Directory.CreateDirectory(newPathToFile);

                newPathToFile = Path.Combine(newPathToFile, name + "_"
                                             + DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss") + extansion);
                Archivation.Decompress(newPathToArchive, newPathToFile);

                if (encryptionOptions.NeedToEncrypt)
                {
                    File.WriteAllBytes(newPathToFile, Encryption.Decrypt(newPathToFile, key, iv));
                }
            }
        }
        public static Encryptor <T> CreateEncryptor <T>(
            [NotNull] byte[] encryptionKey,
            out byte[] randomSalt,
            EncryptionOptions options = DefaultOptions)
            where T : SymmetricAlgorithm
        {
            Contract.Requires <ArgumentNullException>(encryptionKey != null);

            return(new Encryptor <T>(encryptionKey, out randomSalt, options));
        }
Exemple #19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Encryptor"/> class
 /// which generates a random initialization vector using the
 /// <see cref="SymmetricAlgorithm.GenerateIV"/> method
 /// of its embedded <see cref="SymmetricAlgorithm"/>.
 /// The new <paramref name="initializationVector"/> must be
 /// preserved, in addition to the <paramref name="encryptionKey"/>,
 /// to decrypt ciphertext created by this encryptor.
 /// </summary>
 /// <param name="algorithm">
 /// An instance of <see cref="SymmetricAlgorithm"/>
 /// to use for an encryption operation.
 /// </param>
 /// <param name="encryptionKey">
 /// A value for the <see cref="SymmetricAlgorithm.Key"/>
 /// of the embedded <see cref="SymmetricAlgorithm"/>.
 /// </param>
 /// <param name="initializationVector">
 /// Returns a new pseudo-random value which has been
 /// generated for the <see cref="SymmetricAlgorithm.IV"/>
 /// of the embedded <see cref="SymmetricAlgorithm"/>.
 /// This value must be preserved, in addition to the
 /// <paramref name="encryptionKey"/>, to decrypt
 /// ciphertext created by this <see cref="Encryptor"/>.
 /// </param>
 /// <param name="options">
 ///
 /// </param>
 internal Encryptor(
     [NotNull] SymmetricAlgorithm algorithm,
     [NotNull] byte[] encryptionKey,
     out byte[] initializationVector,
     EncryptionOptions options)
     : base(algorithm, encryptionKey, out initializationVector, options)
 {
     Contract.Requires <ArgumentNullException>(algorithm != null);
     Contract.Requires <ArgumentNullException>(encryptionKey != null);
 }
Exemple #20
0
        public EncryptionServiceTest()
        {
            _options = new EncryptionOptions
            {
                Key = "Ha7d31+5tnLm7QrWyEBis7iXb7bcMdzFGp6DSltH+RI=",
                InitializationVector = "P6pYi+oyPqpfZxfdYkwAWQ=="
            };

            _service = new EncryptionService(new OptionsWrapper <EncryptionOptions>(_options));
        }
 protected ConsiderateCryptoStreamAndRfc2898Encryption(
     EncryptionOptions options,
     TSymmetricAlgorithm symmetricAlgorithm,
     string password)
     : base(
         options,
         symmetricAlgorithm,
         deriveBytesFactory: (source, salt, iterationCount) => new Rfc2898DeriveBytes(source, salt, iterationCount),
         password: password)
 {
 }
        public SettingsContainer(IContainer <T> container, byte[] password, EncryptionOptions options, ushort saltSize, int iterations)
        {
            _container  = container;
            _options    = options;
            _saltSize   = saltSize;
            _iterations = iterations;

            //Secure password in memory
            fixed(byte *ptr = password)
            _password = new SecureString((char *)ptr, password.Length / sizeof(char));
        }
        public static Encryptor CreateEncryptor(
            [NotNull] this SymmetricAlgorithm algorithm,
            [NotNull] byte[] encryptionKey,
            out byte[] randomSalt,
            EncryptionOptions options = DefaultOptions)
        {
            Contract.Requires <ArgumentNullException>(algorithm != null);
            Contract.Requires <ArgumentNullException>(encryptionKey != null);

            return(new Encryptor(algorithm, encryptionKey, out randomSalt, options));
        }
        public static EncryptorWithChecksum <TEncryptor, THasher> CreateEncryptor <TEncryptor, THasher>(
            [NotNull] byte[] encryptionKey,
            out byte[] randomSalt,
            EncryptionOptions options = DefaultOptions)
            where TEncryptor : SymmetricAlgorithm
            where THasher : KeyedHashAlgorithm
        {
            Contract.Requires <ArgumentNullException>(encryptionKey != null);

            return(new EncryptorWithChecksum <TEncryptor, THasher>(encryptionKey, out randomSalt, options));
        }
Exemple #25
0
        /* This method not only returns ciphertext, but also the IV and the SALT,
         * which is important for the deciphering on the JS side. Having the same
         * IV and same SALT as suggested by demos on Stackoverflow, etc, is detrimental
         * to the security. IV and SALT can be sent openly alongside ciphertext. An
         * attacker cannot make anything with IV and SALT without the password.
         * Explanation: With different IV, the same plaintext always results in different
         * ciphertexts. With different SALTS, the same password always results in different
         * ciphertexts. The ciphertext will be a JSON Object:
         */
        /*
         * {
         *  "DerivationType": "scrypt", // optionally: rfc
         *  "Salt": "3a069e9126af66a839067f8a272081136d8ce63ed72176dc8a29973d2b15361f", //SALT must be in Hex
         *  "Cost": 16384, //only for DerivationType "scrypt", not for "rfc"
         *  "BlockSize": 8, //only for DerivationType "scrypt", not for "rfc"
         *  "Parallel": 1, //only for DerivationType "scrypt", not for "rfc"
         *  "KeySizeInBytes": 32,
         *  "DerivationIterations": 0 // Only for DerivationType "rfc", not needed for "scrypt"
         *
         * }
         */
        public static string Encrypt(string plainText, string passPhrase, EncryptionOptions eO = null)
        {
            // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
            // so that the same Salt and IV values can be used when decrypting.
            var cipherObject = BasicAesEncryption(new System.Text.UTF8Encoding().GetBytes(plainText), passPhrase, eO);

            var    cipherWithSaltAndIvObject = cipherObject.ConvertToCipherTextObject();//new CipherResultText(eO, cipherObject.CipherOutput);
            string json = JsonConvert.SerializeObject(cipherWithSaltAndIvObject, Formatting.None);

            return(json);
        }
        // The resulting CipherResult contains all important settings (options) and the resulting CipherText (in Byte Array)
        public static CipherResult BasicAesEncryption(byte[] bytesToEncrypt, string passPhrase, EncryptionOptions eO = null)
        {
            // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
            // so that the same Salt and IV values can be used when decrypting.
            var myRijndael = new RijndaelManaged();

            myRijndael.BlockSize = 128;
            if (eO == null)
            {
                eO            = new EncryptionOptions();
                myRijndael.IV = GenerateXBytesOfRandomEntropy(16); //IV must be 16 bytes / 128 bit
                eO.RijndaelIv = myRijndael.IV;
            }
            else if (eO.RijndaelIv == null)
            {
                myRijndael.IV = GenerateXBytesOfRandomEntropy(16); //IV must be 16 bytes / 128 bit
                eO.RijndaelIv = myRijndael.IV;
            }
            else
            {
                myRijndael.IV = eO.RijndaelIv;
            }

            myRijndael.Padding = PaddingMode.PKCS7;
            myRijndael.Mode    = CipherMode.CBC;

            // Using Scrypt for Key Derivation
            if (eO.DerivationType == null || eO.DerivationType == "scrypt")
            {
                eO.DerivationType = "scrypt";
                myRijndael.Key    =
                    ScryptHandler.GetOnlyHashBytes(System.Text.Encoding.UTF8.GetBytes(passPhrase), eO);
            }
            // Using RFC2898 for Key Derivation
            else
            {
                if (eO.Salt == null)
                {
                    eO.Salt = GenerateXBytesOfRandomEntropy(32);
                }
                myRijndael.KeySize = eO.KeySizeInBytes * 8;
                Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetBytes(passPhrase), eO.Salt,
                                                                    eO.DerivationIterations);
                myRijndael.Key = rfc2898.GetBytes(eO.KeySizeInBytes);
            }

            byte[]           utf8Text  = bytesToEncrypt;
            ICryptoTransform transform = myRijndael.CreateEncryptor();

            byte[] cipherText = transform.TransformFinalBlock(utf8Text, 0, utf8Text.Length);
            var    cipherWithSaltAndIvObject = new CipherResult(eO, cipherText);

            return(cipherWithSaltAndIvObject);
        }
 internal EncryptorWithChecksum(
     [NotNull] SymmetricAlgorithm symmetricAlgorithm,
     [NotNull] KeyedHashAlgorithm checksumHasher,
     [NotNull] byte[] encryptionKey,
     out byte[] initializationVector,
     EncryptionOptions options)
     : base(symmetricAlgorithm, checksumHasher, encryptionKey, out initializationVector, options)
 {
     Contract.Requires <ArgumentNullException>(symmetricAlgorithm != null);
     Contract.Requires <ArgumentNullException>(checksumHasher != null);
     Contract.Requires <ArgumentNullException>(encryptionKey != null);
 }
Exemple #28
0
        public void Insert(string key, T value, byte[] password, EncryptionOptions options, ushort saltSize, int iterations)
        {
            if (ResolveKeys(password, iterations).Contains(key))
            {
                throw Error.Argument(nameof(key), $"An element with the same key already exists ({key})");
            }

            if (_storage.CanMerge)
            {
                //We can append!
                using (var fs = _storage.Append())
                {
                    if (_storage.HasOffsets)
                    {
                        var offset = (ushort)(fs.Length);

                        var indexes    = _storage.ResolveIndexes();
                        var newIndexes = new byte[indexes.Length + sizeof(ushort)];
                        Array.Copy(indexes, newIndexes, indexes.Length);

                        fixed(byte *b = &newIndexes[indexes.Length])
                        {
                            *((ushort *)b) = offset;
                        }

                        _storage.WriteIndex(newIndexes);
                    }

                    var encrypted = _security.Encrypt(key, value, password, options, saltSize, iterations);
                    fs.Write(encrypted, 0, encrypted.Length);
                    encrypted.Clear();
                }
            }
            else
            {
                var dictionary = Decrypt(password, iterations);
                var original   = dictionary.Values.ToArray();

                dictionary[key] = value;

                Encrypt(dictionary, password, options, saltSize, iterations);

                if (typeof(IDisposable).IsAssignableFrom(typeof(T)))
                {
                    //Clean up decrypted keys, make user clean up their own.
                    foreach (var disposable in original.OfType <IDisposable>())
                    {
                        disposable.Dispose();
                    }
                }
            }
        }
        public static Encryptor CreateEncryptorWithGivenSalt(
            [NotNull] this SymmetricAlgorithm algorithm,
            [NotNull] string secretKey,
            [NotNull] string salt,
            ByteArrayStringEncoding saltEncoding = ConvertByteArray.DefaultStringEncoding,
            EncryptionOptions options            = DefaultOptions)
        {
            Contract.Requires <ArgumentNullException>(algorithm != null);
            Contract.Requires <ArgumentNullException>(secretKey != null);
            Contract.Requires <ArgumentNullException>(salt != null);

            return(algorithm.CreateEncryptorWithGivenSalt(secretKey, salt.ToByteArray(saltEncoding), options));
        }
Exemple #30
0
 public Rijndael256Encryption(EncryptionOptions options, string password)
     : base(
         options,
         new RijndaelManaged()
 {
     BlockSize = 256,
     KeySize   = 256,
     Mode      = CipherMode.CBC,
     Padding   = PaddingMode.PKCS7
 },
         password)
 {
 }
        public unsafe Stream Read(out EncryptionOptions options)
        {
            var fs = Read();
            
            var bytes = new byte[sizeof(EncryptionOptions)];

            fs.Read(bytes, 0, sizeof(EncryptionOptions));

            fixed (byte* b = bytes)
                options = *(EncryptionOptions*)b;

            _options = options;
            return fs;
        }
 private SNILoadHandle() : base(IntPtr.Zero, true)
 {
     this.ReadAsyncCallbackDispatcher = new SNINativeMethodWrapper.SqlAsyncCallbackDelegate(SNILoadHandle.ReadDispatcher);
     this.WriteAsyncCallbackDispatcher = new SNINativeMethodWrapper.SqlAsyncCallbackDelegate(SNILoadHandle.WriteDispatcher);
     this._sniStatus = uint.MaxValue;
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
     }
     finally
     {
         this._sniStatus = SNINativeMethodWrapper.SNIInitialize();
         uint qInfo = 0;
         if (this._sniStatus == 0)
         {
             SNINativeMethodWrapper.SNIQueryInfo(SNINativeMethodWrapper.QTypes.SNI_QUERY_CLIENT_ENCRYPT_POSSIBLE, ref qInfo);
         }
         this._encryptionOption = (qInfo == 0) ? EncryptionOptions.NOT_SUP : EncryptionOptions.OFF;
         base.handle = (IntPtr) 1;
     }
 }
        private SNILoadHandle() : base(IntPtr.Zero, true) {
            // SQL BU DT 346588 - from security review - SafeHandle guarantees this is only called once.
            // The reason for the safehandle is guaranteed initialization and termination of SNI to
            // ensure SNI terminates and cleans up properly.
            RuntimeHelpers.PrepareConstrainedRegions();
            try {} finally {
                
                _sniStatus = SNINativeMethodWrapper.SNIInitialize();

                UInt32 value = 0;

                // VSDevDiv 479597: If initialize fails, don't call QueryInfo.
                if (TdsEnums.SNI_SUCCESS == _sniStatus) {
                    // Query OS to find out whether encryption is supported.
                    SNINativeMethodWrapper.SNIQueryInfo(SNINativeMethodWrapper.QTypes.SNI_QUERY_CLIENT_ENCRYPT_POSSIBLE, ref value);
                }

                _encryptionOption = (value == 0) ? EncryptionOptions.NOT_SUP : EncryptionOptions.OFF;

                base.handle = (IntPtr) 1; // Initialize to non-zero dummy variable.
            }
        }
        public unsafe Stream Create(EncryptionOptions options)
        {
            _options = options;

            var fs = Create();

            var bytes = new byte[sizeof(EncryptionOptions)];

            fixed (byte* b = bytes)
                UnsafeNativeMethods.memcpy(b, &options, sizeof(EncryptionOptions));

            fs.Write(bytes, 0, sizeof(EncryptionOptions));

            return fs;
        }
Exemple #35
0
        private PreLoginHandshakeStatus ConsumePreLoginHandshake(bool encrypt, bool trustServerCert, bool integratedSecurity, out bool marsCapable)
        {
            marsCapable = _fMARS; // Assign default value

            bool isYukonOrLater = false;
            Debug.Assert(_physicalStateObj._syncOverAsync, "Should not attempt pends in a synchronous call");
            bool result = _physicalStateObj.TryReadNetworkPacket();
            if (!result) { throw SQL.SynchronousCallMayNotPend(); }

            if (_physicalStateObj._inBytesRead == 0)
            {
                // If the server did not respond then something has gone wrong and we need to close the connection
                _physicalStateObj.AddError(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.PreloginError(), "", 0));
                _physicalStateObj.Dispose();
                ThrowExceptionAndWarning(_physicalStateObj);
            }

            // _inBuff should only be 4k at this point, so we eliminate ways for rogue server to provide large buffer resulting in DOS.
            byte[] payload = new byte[_physicalStateObj._inBytesRead - _physicalStateObj._inBytesUsed - _physicalStateObj._inputHeaderLen];

            Debug.Assert(_physicalStateObj._syncOverAsync, "Should not attempt pends in a synchronous call");
            result = _physicalStateObj.TryReadByteArray(payload, 0, payload.Length);
            if (!result) { throw SQL.SynchronousCallMayNotPend(); }

            if (payload[0] == 0xaa)
            {
                // If the first byte is 0xAA, we are connecting to a 6.5 or earlier server, which
                // is not supported. 
                throw SQL.InvalidSQLServerVersionUnknown();
            }

            int offset = 0;
            int payloadOffset = 0;
            int payloadLength = 0;
            int option = payload[offset++];

            while (option != (byte)PreLoginOptions.LASTOPT)
            {
                switch (option)
                {
                    case (int)PreLoginOptions.VERSION:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        byte majorVersion = payload[payloadOffset];
                        byte minorVersion = payload[payloadOffset + 1];
                        int level = (payload[payloadOffset + 2] << 8) |
                                             payload[payloadOffset + 3];

                        isYukonOrLater = majorVersion >= 9;
                        if (!isYukonOrLater)
                        {
                            marsCapable = false;            // If pre-Yukon, MARS not supported.
                        }

                        break;

                    case (int)PreLoginOptions.ENCRYPT:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        EncryptionOptions serverOption = (EncryptionOptions)payload[payloadOffset];

                        /* internal enum EncryptionOptions {
                            OFF,
                            ON,
                            NOT_SUP,
                            REQ,
                            LOGIN
                        } */

                        switch (_encryptionOption)
                        {
                            case (EncryptionOptions.ON):
                                if (serverOption == EncryptionOptions.NOT_SUP)
                                {
                                    _physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByServer(), "", 0));
                                    _physicalStateObj.Dispose();
                                    ThrowExceptionAndWarning(_physicalStateObj);
                                }

                                break;

                            case (EncryptionOptions.OFF):
                                if (serverOption == EncryptionOptions.OFF)
                                {
                                    // Only encrypt login.
                                    _encryptionOption = EncryptionOptions.LOGIN;
                                }
                                else if (serverOption == EncryptionOptions.REQ)
                                {
                                    // Encrypt all.
                                    _encryptionOption = EncryptionOptions.ON;
                                }

                                break;

                            case (EncryptionOptions.NOT_SUP):
                                if (serverOption == EncryptionOptions.REQ)
                                {
                                    _physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByClient(), "", 0));
                                    _physicalStateObj.Dispose();
                                    ThrowExceptionAndWarning(_physicalStateObj);
                                }

                                break;

                            default:
                                Debug.Assert(false, "Invalid client encryption option detected");
                                break;
                        }

                        if (_encryptionOption == EncryptionOptions.ON ||
                            _encryptionOption == EncryptionOptions.LOGIN)
                        {
                            UInt32 error = 0;
                            UInt32 info = ((encrypt && !trustServerCert) ? TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE : 0)
                                | (isYukonOrLater ? TdsEnums.SNI_SSL_USE_SCHANNEL_CACHE : 0);


                            if (encrypt && !integratedSecurity)
                            {
                                // optimization: in case of SQL Authentication and encryption, set SNI_SSL_IGNORE_CHANNEL_BINDINGS to let SNI 
                                // know that it does not need to allocate/retrieve the Channel Bindings from the SSL context.
                                info |= TdsEnums.SNI_SSL_IGNORE_CHANNEL_BINDINGS;
                            }

                            // Add SSL (Encryption) SNI provider.
                            error = SNINativeMethodWrapper.SNIAddProvider(_physicalStateObj.Handle, SNINativeMethodWrapper.ProviderEnum.SSL_PROV, ref info);

                            if (error != TdsEnums.SNI_SUCCESS)
                            {
                                _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
                                ThrowExceptionAndWarning(_physicalStateObj);
                            }

                            // in the case where an async connection is made, encryption is used and Windows Authentication is used, 
                            // wait for SSL handshake to complete, so that the SSL context is fully negotiated before we try to use its 
                            // Channel Bindings as part of the Windows Authentication context build (SSL handshake must complete 
                            // before calling SNISecGenClientContext).
                            error = SNINativeMethodWrapper.SNIWaitForSSLHandshakeToComplete(_physicalStateObj.Handle, _physicalStateObj.GetTimeoutRemaining());
                            if (error != TdsEnums.SNI_SUCCESS)
                            {
                                _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
                                ThrowExceptionAndWarning(_physicalStateObj);
                            }

                            // create a new packet encryption changes the internal packet size
                            try { } // EmptyTry/Finally to avoid FXCop violation
                            finally
                            {
                                _physicalStateObj.ClearAllWritePackets();
                            }
                        }

                        break;

                    case (int)PreLoginOptions.INSTANCE:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        byte ERROR_INST = 0x1;
                        byte instanceResult = payload[payloadOffset];

                        if (instanceResult == ERROR_INST)
                        {
                            // Check if server says ERROR_INST. That either means the cached info
                            // we used to connect is not valid or we connected to a named instance
                            // listening on default params.
                            return PreLoginHandshakeStatus.InstanceFailure;
                        }

                        break;

                    case (int)PreLoginOptions.THREADID:
                        // DO NOTHING FOR THREADID
                        offset += 4;
                        break;

                    case (int)PreLoginOptions.MARS:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        marsCapable = (payload[payloadOffset] == 0 ? false : true);

                        Debug.Assert(payload[payloadOffset] == 0 || payload[payloadOffset] == 1, "Value for Mars PreLoginHandshake option not equal to 1 or 0!");
                        break;

                    case (int)PreLoginOptions.TRACEID:
                        // DO NOTHING FOR TRACEID
                        offset += 4;
                        break;

                    default:
                        Debug.Assert(false, "UNKNOWN option in ConsumePreLoginHandshake, option:" + option);

                        // DO NOTHING FOR THESE UNKNOWN OPTIONS
                        offset += 4;

                        break;
                }

                if (offset < payload.Length)
                {
                    option = payload[offset++];
                }
                else
                {
                    break;
                }
            }

            return PreLoginHandshakeStatus.Successful;
        }
Exemple #36
0
        private void SendPreLoginHandshake(byte[] instanceName, bool encrypt)
        {
            // PreLoginHandshake buffer consists of:
            // 1) Standard header, with type = MT_PRELOGIN
            // 2) Consecutive 5 bytes for each option, (1 byte length, 2 byte offset, 2 byte payload length)
            // 3) Consecutive data blocks for each option

            // NOTE: packet data needs to be big endian - not the standard little endian used by
            // the rest of the parser.

            _physicalStateObj._outputMessageType = TdsEnums.MT_PRELOGIN;

            // Initialize option offset into payload buffer
            // 5 bytes for each option (1 byte length, 2 byte offset, 2 byte payload length)
            int offset = (int)PreLoginOptions.NUMOPT * 5 + 1;

            byte[] payload = new byte[(int)PreLoginOptions.NUMOPT * 5 + TdsEnums.MAX_PRELOGIN_PAYLOAD_LENGTH];
            int payloadLength = 0;

            for (int option = (int)PreLoginOptions.VERSION; option < (int)PreLoginOptions.NUMOPT; option++)
            {
                int optionDataSize = 0;

                // Fill in the option
                _physicalStateObj.WriteByte((byte)option);

                // Fill in the offset of the option data
                _physicalStateObj.WriteByte((byte)((offset & 0xff00) >> 8)); // send upper order byte
                _physicalStateObj.WriteByte((byte)(offset & 0x00ff)); // send lower order byte

                switch (option)
                {
                    case (int)PreLoginOptions.VERSION:
                        Version systemDataVersion = ADP.GetAssemblyVersion();

                        // Major and minor
                        payload[payloadLength++] = (byte)(systemDataVersion.Major & 0xff);
                        payload[payloadLength++] = (byte)(systemDataVersion.Minor & 0xff);

                        // Build (Big Endian)
                        payload[payloadLength++] = (byte)((systemDataVersion.Build & 0xff00) >> 8);
                        payload[payloadLength++] = (byte)(systemDataVersion.Build & 0xff);

                        // Sub-build (Little Endian)
                        payload[payloadLength++] = (byte)(systemDataVersion.Revision & 0xff);
                        payload[payloadLength++] = (byte)((systemDataVersion.Revision & 0xff00) >> 8);
                        offset += 6;
                        optionDataSize = 6;
                        break;

                    case (int)PreLoginOptions.ENCRYPT:
                        if (_encryptionOption == EncryptionOptions.NOT_SUP)
                        {
                            // If OS doesn't support encryption, inform server not supported.
                            payload[payloadLength] = (byte)EncryptionOptions.NOT_SUP;
                        }
                        else
                        {
                            // Else, inform server of user request.
                            if (encrypt)
                            {
                                payload[payloadLength] = (byte)EncryptionOptions.ON;
                                _encryptionOption = EncryptionOptions.ON;
                            }
                            else
                            {
                                payload[payloadLength] = (byte)EncryptionOptions.OFF;
                                _encryptionOption = EncryptionOptions.OFF;
                            }
                        }

                        payloadLength += 1;
                        offset += 1;
                        optionDataSize = 1;
                        break;

                    case (int)PreLoginOptions.INSTANCE:
                        int i = 0;

                        while (instanceName[i] != 0)
                        {
                            payload[payloadLength] = instanceName[i];
                            payloadLength++;
                            i++;
                        }

                        payload[payloadLength] = 0; // null terminate
                        payloadLength++;
                        i++;

                        offset += i;
                        optionDataSize = i;
                        break;

                    case (int)PreLoginOptions.THREADID:
                        Int32 threadID = TdsParserStaticMethods.GetCurrentThreadIdForTdsLoginOnly();

                        payload[payloadLength++] = (byte)((0xff000000 & threadID) >> 24);
                        payload[payloadLength++] = (byte)((0x00ff0000 & threadID) >> 16);
                        payload[payloadLength++] = (byte)((0x0000ff00 & threadID) >> 8);
                        payload[payloadLength++] = (byte)(0x000000ff & threadID);
                        offset += 4;
                        optionDataSize = 4;
                        break;

                    case (int)PreLoginOptions.MARS:
                        payload[payloadLength++] = (byte)(_fMARS ? 1 : 0);
                        offset += 1;
                        optionDataSize += 1;
                        break;

                    case (int)PreLoginOptions.TRACEID:
                        byte[] connectionIdBytes = _connHandler._clientConnectionId.ToByteArray();
                        Debug.Assert(GUID_SIZE == connectionIdBytes.Length);
                        Buffer.BlockCopy(connectionIdBytes, 0, payload, payloadLength, GUID_SIZE);
                        payloadLength += GUID_SIZE;
                        offset += GUID_SIZE;
                        optionDataSize = GUID_SIZE;

                        ActivityCorrelator.ActivityId actId = ActivityCorrelator.Next();
                        connectionIdBytes = actId.Id.ToByteArray();
                        Buffer.BlockCopy(connectionIdBytes, 0, payload, payloadLength, GUID_SIZE);
                        payloadLength += GUID_SIZE;
                        payload[payloadLength++] = (byte)(0x000000ff & actId.Sequence);
                        payload[payloadLength++] = (byte)((0x0000ff00 & actId.Sequence) >> 8);
                        payload[payloadLength++] = (byte)((0x00ff0000 & actId.Sequence) >> 16);
                        payload[payloadLength++] = (byte)((0xff000000 & actId.Sequence) >> 24);
                        int actIdSize = GUID_SIZE + sizeof(UInt32);
                        offset += actIdSize;
                        optionDataSize += actIdSize;
                        break;

                    default:
                        Debug.Assert(false, "UNKNOWN option in SendPreLoginHandshake");
                        break;
                }

                // Write data length
                _physicalStateObj.WriteByte((byte)((optionDataSize & 0xff00) >> 8));
                _physicalStateObj.WriteByte((byte)(optionDataSize & 0x00ff));
            }

            // Write out last option - to let server know the second part of packet completed
            _physicalStateObj.WriteByte((byte)PreLoginOptions.LASTOPT);

            // Write out payload
            _physicalStateObj.WriteByteArray(payload, payloadLength, 0);

            // Flush packet
            _physicalStateObj.WritePacket(TdsEnums.HARDFLUSH);
        }
        private PreLoginHandshakeStatus ConsumePreLoginHandshake(SqlAuthenticationMethod authType, bool encrypt, bool trustServerCert, bool integratedSecurity, out bool marsCapable, out bool fedAuthRequired) {

            // Assign default values
            marsCapable = _fMARS;
            fedAuthRequired = false;

            bool isYukonOrLater = false;

            // 

            Debug.Assert(_physicalStateObj._syncOverAsync, "Should not attempt pends in a synchronous call");
            bool result = _physicalStateObj.TryReadNetworkPacket();
            if (!result) { throw SQL.SynchronousCallMayNotPend(); }

            if (_physicalStateObj._inBytesRead == 0) {
                // If the server did not respond then something has gone wrong and we need to close the connection
                _physicalStateObj.AddError(new SqlError(0, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.PreloginError(), "", 0));
                _physicalStateObj.Dispose();
                ThrowExceptionAndWarning(_physicalStateObj);
            }

            // SEC 
            byte[] payload = new byte[_physicalStateObj._inBytesRead - _physicalStateObj._inBytesUsed - _physicalStateObj._inputHeaderLen];

            Debug.Assert(_physicalStateObj._syncOverAsync, "Should not attempt pends in a synchronous call");
            result = _physicalStateObj.TryReadByteArray(payload, 0, payload.Length);
            if (!result) { throw SQL.SynchronousCallMayNotPend(); }

            if (payload[0] == 0xaa) {
                // If the first byte is 0xAA, we are connecting to a 6.5 or earlier server, which
                // is not supported.  SQL BU DT 296425
                throw SQL.InvalidSQLServerVersionUnknown();
            }

            int offset = 0;
            int payloadOffset = 0;
            int payloadLength = 0;
            int option = payload[offset++];

            while (option != (byte)PreLoginOptions.LASTOPT) {
                switch (option) {
                    case (int)PreLoginOptions.VERSION:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        byte majorVersion = payload[payloadOffset];
                        byte minorVersion = payload[payloadOffset + 1];
                        int level = (payload[payloadOffset + 2] << 8) |
                                             payload[payloadOffset + 3];

                        isYukonOrLater = majorVersion >= 9;
                        if (!isYukonOrLater) {
                            marsCapable = false;            // If pre-Yukon, MARS not supported.
                        }

                        break;

                    case (int)PreLoginOptions.ENCRYPT:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        EncryptionOptions serverOption = (EncryptionOptions)payload[payloadOffset];

                        /* internal enum EncryptionOptions {
                            OFF,
                            ON,
                            NOT_SUP,
                            REQ,
                            LOGIN
                        } */

                        switch (_encryptionOption) {
                            case (EncryptionOptions.ON):
                                if (serverOption == EncryptionOptions.NOT_SUP) {
                                    _physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByServer(), "", 0));
                                    _physicalStateObj.Dispose();
                                    ThrowExceptionAndWarning(_physicalStateObj);
                                }

                                break;

                            case (EncryptionOptions.OFF):
                                if (serverOption == EncryptionOptions.OFF) {
                                    // Only encrypt login.
                                    _encryptionOption = EncryptionOptions.LOGIN;
                                }
                                else if (serverOption == EncryptionOptions.REQ) {
                                    // Encrypt all.
                                    _encryptionOption = EncryptionOptions.ON;
                                }

                                break;

                            case (EncryptionOptions.NOT_SUP):
                                if (serverOption == EncryptionOptions.REQ) {
                                    _physicalStateObj.AddError(new SqlError(TdsEnums.ENCRYPTION_NOT_SUPPORTED, (byte)0x00, TdsEnums.FATAL_ERROR_CLASS, _server, SQLMessage.EncryptionNotSupportedByClient(), "", 0));
                                    _physicalStateObj.Dispose();
                                    ThrowExceptionAndWarning(_physicalStateObj);
                                }

                                break;

                            default:
                                Debug.Assert(false, "Invalid client encryption option detected");
                                break;
                        }

                        if (_encryptionOption == EncryptionOptions.ON ||
                            _encryptionOption == EncryptionOptions.LOGIN) {
                            UInt32 error = 0;
                            
                            // If we're using legacy server certificate validation behavior (Authentication keyword not provided and not using access token), then validate if
                            //     Encrypt=true and Trust Sever Certificate = false.
                            // If using Authentication keyword or access token, validate if Trust Server Certificate=false.
                            bool shouldValidateServerCert = (encrypt && !trustServerCert) || ((authType != SqlAuthenticationMethod.NotSpecified || _connHandler._accessTokenInBytes != null) && !trustServerCert);

                            UInt32 info = (shouldValidateServerCert ? TdsEnums.SNI_SSL_VALIDATE_CERTIFICATE : 0)
                                | (isYukonOrLater ? TdsEnums.SNI_SSL_USE_SCHANNEL_CACHE : 0);

                            if (encrypt && !integratedSecurity) {
                                // optimization: in case of SQL Authentication and encryption, set SNI_SSL_IGNORE_CHANNEL_BINDINGS to let SNI 
                                // know that it does not need to allocate/retrieve the Channel Bindings from the SSL context.
                                info |= TdsEnums.SNI_SSL_IGNORE_CHANNEL_BINDINGS;
                            }

                            // Add SSL (Encryption) SNI provider.
                            error = SNINativeMethodWrapper.SNIAddProvider(_physicalStateObj.Handle, SNINativeMethodWrapper.ProviderEnum.SSL_PROV, ref info);

                            if (error != TdsEnums.SNI_SUCCESS) {
                                _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
                                ThrowExceptionAndWarning(_physicalStateObj);
                            }

                            // in the case where an async connection is made, encryption is used and Windows Authentication is used, 
                            // wait for SSL handshake to complete, so that the SSL context is fully negotiated before we try to use its 
                            // Channel Bindings as part of the Windows Authentication context build (SSL handshake must complete 
                            // before calling SNISecGenClientContext).
                            error = SNINativeMethodWrapper.SNIWaitForSSLHandshakeToComplete(_physicalStateObj.Handle, _physicalStateObj.GetTimeoutRemaining());
                            if (error != TdsEnums.SNI_SUCCESS)
                            {
                                _physicalStateObj.AddError(ProcessSNIError(_physicalStateObj));
                                ThrowExceptionAndWarning(_physicalStateObj);
                            }

                            // create a new packet encryption changes the internal packet size Bug# 228403
                            try {} // EmptyTry/Finally to avoid FXCop violation
                            finally {
                                _physicalStateObj.ClearAllWritePackets();
                             }
                        }

                        break;

                    case (int)PreLoginOptions.INSTANCE:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        byte ERROR_INST = 0x1;
                        byte instanceResult = payload[payloadOffset];

                        if (instanceResult == ERROR_INST) {
                            // Check if server says ERROR_INST. That either means the cached info
                            // we used to connect is not valid or we connected to a named instance
                            // listening on default params.
                            return PreLoginHandshakeStatus.InstanceFailure;
                        }

                        break;

                    case (int)PreLoginOptions.THREADID:
                        // DO NOTHING FOR THREADID
                        offset += 4;
                        break;

                    case (int)PreLoginOptions.MARS:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        marsCapable = (payload[payloadOffset] == 0 ? false : true);

                        Debug.Assert(payload[payloadOffset] == 0 || payload[payloadOffset] == 1, "Value for Mars PreLoginHandshake option not equal to 1 or 0!");
                        break;

                    case (int)PreLoginOptions.TRACEID:
                        // DO NOTHING FOR TRACEID
                        offset += 4;
                        break;

                    case (int)PreLoginOptions.FEDAUTHREQUIRED:
                        payloadOffset = payload[offset++] << 8 | payload[offset++];
                        payloadLength = payload[offset++] << 8 | payload[offset++];

                        // Only 0x00 and 0x01 are accepted values from the server.
                        if (payload[payloadOffset] != 0x00 && payload[payloadOffset] != 0x01) {
                            Bid.Trace("<sc.TdsParser.ConsumePreLoginHandshake|ERR> %d#, Server sent an unexpected value for FedAuthRequired PreLogin Option. Value was %d.\n", ObjectID, (int)payload[payloadOffset]);
                            throw SQL.ParsingErrorValue(ParsingErrorState.FedAuthRequiredPreLoginResponseInvalidValue, (int)payload[payloadOffset]);
                        }

                        // We must NOT use the response for the FEDAUTHREQUIRED PreLogin option, if the connection string option
                        // was not using the new Authentication keyword or in other words, if Authentication=NotSpecified
                        // Or AccessToken is not null, mean token based authentication is used.
                        if ((_connHandler.ConnectionOptions != null
                            && _connHandler.ConnectionOptions.Authentication != SqlAuthenticationMethod.NotSpecified)
                            || _connHandler._accessTokenInBytes != null) 
                        {
                            fedAuthRequired = payload[payloadOffset] == 0x01 ? true : false;
                        }
                        break;

                    default:
                        Debug.Assert(false, "UNKNOWN option in ConsumePreLoginHandshake, option:" + option);

                        // DO NOTHING FOR THESE UNKNOWN OPTIONS
                        offset += 4;

                        break;
                }

                if (offset < payload.Length) {
                    option = payload[offset++];
                }
                else {
                    break;
                }
            }

            return PreLoginHandshakeStatus.Successful;
        }