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); }
/// <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)); } }
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. } }
public static CipherResult BinaryEncryptWithStaticIv(byte[] fileToEncrypt, string passPhrase, EncryptionOptions eO = null) { var cipherObject = BasicAesEncryption(fileToEncrypt, passPhrase, eO); return(cipherObject); }
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); }
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); } }
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))); }
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(); } } }
/// <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; } }
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); }
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; }
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; }
public IConnectionBuilder Encryption(EncryptionOptions Encryption) { if (this.IsLocked == true) { throw new BuilderLockedException(this.GetType().FullName); } this.e_Encryption = Encryption; return(this); }
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)); }
/// <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); }
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)); }
/* 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); }
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)); }
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; }
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; }
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; }