mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 10:56:10 +00:00
1084 lines
42 KiB
C#
1084 lines
42 KiB
C#
|
// Decompiled with JetBrains decompiler
|
|||
|
// Type: Microsoft.InfoCards.FileDataSource
|
|||
|
// Assembly: infocard, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
|
|||
|
// MVID: ADE0A079-11DB-4A46-8BDE-D2A592CA8DEA
|
|||
|
// Assembly location: C:\Users\Administrateur\Downloads\Virusshare-00000-msil\Virus.Win32.Expiro.w-67b630ead60119692b9abbdfd8717c96904ef041127c2cae033c86b718eaa61e.exe
|
|||
|
|
|||
|
using Microsoft.InfoCards.Diagnostics;
|
|||
|
using System;
|
|||
|
using System.Collections;
|
|||
|
using System.ComponentModel;
|
|||
|
using System.IO;
|
|||
|
using System.Runtime.InteropServices;
|
|||
|
using System.Security.AccessControl;
|
|||
|
using System.Security.Cryptography;
|
|||
|
using System.Security.Principal;
|
|||
|
using System.Text;
|
|||
|
using System.Threading;
|
|||
|
|
|||
|
namespace Microsoft.InfoCards
|
|||
|
{
|
|||
|
internal class FileDataSource : DataSource
|
|||
|
{
|
|||
|
public const int ENCRYPTIONKEYBUFFERSIZE = 32;
|
|||
|
public const int ENCRYPTIONKEYBITLENGTH = 256;
|
|||
|
public const int ENCRYPTIONBLOCKBUFFERSIZE = 16;
|
|||
|
public const int ENCRYPTIONBLOCKBITLENGTH = 128;
|
|||
|
public const int ENCRYPTIONITERATIONS = 1000;
|
|||
|
public const int INITIALINDEXITEMCOUNT = 20;
|
|||
|
public const int INITIALINDEXAREASIZE = 80;
|
|||
|
public const int INITIALBLOBAREASIZE = 2048;
|
|||
|
public const int FILEVERSION = 11;
|
|||
|
public const int FILEVERSIONV2 = 12;
|
|||
|
private static readonly SecurityIdentifier AdministratorSid = new SecurityIdentifier(WellKnownSidType.BuiltinAdministratorsSid, (SecurityIdentifier) null);
|
|||
|
private int m_variableSignatureLength = 64;
|
|||
|
private FileInfo m_fileInfo;
|
|||
|
private FileStream m_file;
|
|||
|
private FileInfo m_shadowInfo;
|
|||
|
private FileStream m_shadow;
|
|||
|
private byte[] m_header;
|
|||
|
private IndexedDataBuffer m_data;
|
|||
|
private SecondaryIndexList m_indexes;
|
|||
|
private ReaderWriterLock m_lock;
|
|||
|
private SymmetricAlgorithm m_encAlg;
|
|||
|
private byte[] m_key;
|
|||
|
private bool m_keyProtected;
|
|||
|
private WindowsIdentity m_identity;
|
|||
|
private bool m_currentTransactionDirty;
|
|||
|
private SafeRsaProviderHandle m_provider;
|
|||
|
private byte[] m_encryptedKey;
|
|||
|
|
|||
|
protected FileDataSource()
|
|||
|
: base((string) null, (string) null)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public FileDataSource(WindowsIdentity identity, string fileName)
|
|||
|
: this(identity, fileName, Guid.NewGuid().ToString("P"), SecondaryIndexDefinition.MasterIndexes)
|
|||
|
{
|
|||
|
}
|
|||
|
|
|||
|
public FileDataSource(
|
|||
|
WindowsIdentity identity,
|
|||
|
string fileName,
|
|||
|
string instanceId,
|
|||
|
SecondaryIndexDefinition[] indexDefinitions)
|
|||
|
: base(instanceId, fileName)
|
|||
|
{
|
|||
|
this.m_identity = identity;
|
|||
|
this.m_currentTransactionDirty = false;
|
|||
|
this.m_fileInfo = new FileInfo(fileName);
|
|||
|
this.m_shadowInfo = new FileInfo(this.m_fileInfo.FullName + ".shadow");
|
|||
|
this.m_lock = new ReaderWriterLock();
|
|||
|
this.m_indexes = new SecondaryIndexList(indexDefinitions);
|
|||
|
this.m_encAlg = FileDataSource.CreateEncryptionAlg();
|
|||
|
this.SetupProvider();
|
|||
|
}
|
|||
|
|
|||
|
public IndexedDataBuffer Buffer
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
this.ThrowIfDisposed();
|
|||
|
this.ThrowIfNotLoaded();
|
|||
|
return this.m_data;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public byte[] Header
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
this.ThrowIfDisposed();
|
|||
|
this.ThrowIfNotLoaded();
|
|||
|
return this.m_header;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public SecondaryIndexList Indexes
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
this.ThrowIfDisposed();
|
|||
|
this.ThrowIfNotLoaded();
|
|||
|
return this.m_indexes;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected WindowsIdentity Identity => this.m_identity;
|
|||
|
|
|||
|
protected internal override void OnClear()
|
|||
|
{
|
|||
|
using (new SystemIdentity(true))
|
|||
|
{
|
|||
|
FileDataSource.ResilientDelete(this.m_fileInfo);
|
|||
|
FileDataSource.ResilientDelete(this.m_shadowInfo);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected internal override void OnLoad()
|
|||
|
{
|
|||
|
this.ThrowIfDisposed();
|
|||
|
try
|
|||
|
{
|
|||
|
this.CreateDirAndFiles();
|
|||
|
if (this.m_shadow.Length > 0L)
|
|||
|
{
|
|||
|
if (this.m_file.Length > 0L)
|
|||
|
{
|
|||
|
this.m_shadow.SetLength(0L);
|
|||
|
this.LoadFrom((Stream) this.m_file);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.LoadFrom((Stream) this.m_shadow);
|
|||
|
this.FlushToShadow();
|
|||
|
this.SwapFileWithShadow();
|
|||
|
}
|
|||
|
}
|
|||
|
else if (this.m_file.Length > 0L)
|
|||
|
{
|
|||
|
this.LoadFrom((Stream) this.m_file);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
this.CreateEmptyStore();
|
|||
|
this.FlushToShadow();
|
|||
|
this.SwapFileWithShadow();
|
|||
|
}
|
|||
|
this.m_file.Seek(0L, SeekOrigin.Begin);
|
|||
|
}
|
|||
|
catch
|
|||
|
{
|
|||
|
this.CloseFiles();
|
|||
|
throw;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void CloseFiles()
|
|||
|
{
|
|||
|
using (new SystemIdentity(false))
|
|||
|
{
|
|||
|
if (this.m_file != null)
|
|||
|
{
|
|||
|
this.m_file.Close();
|
|||
|
this.m_file = (FileStream) null;
|
|||
|
}
|
|||
|
if (this.m_shadow == null)
|
|||
|
return;
|
|||
|
this.m_shadow.Close();
|
|||
|
this.m_shadow = (FileStream) null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected void CreateDirAndFiles()
|
|||
|
{
|
|||
|
this.CheckReparsePoints();
|
|||
|
if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName))
|
|||
|
this.ValidateDirectoryAccess();
|
|||
|
using (new SystemIdentity(true))
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (!this.m_fileInfo.Directory.Exists)
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName))
|
|||
|
this.m_fileInfo.Directory.Create(FileDataSource.CreateSecurityDescriptor<DirectorySecurity>());
|
|||
|
else
|
|||
|
this.m_fileInfo.Directory.Create();
|
|||
|
this.m_fileInfo.Directory.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed;
|
|||
|
}
|
|||
|
catch (UnauthorizedAccessException ex)
|
|||
|
{
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(ex.Message));
|
|||
|
}
|
|||
|
}
|
|||
|
else if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName) && this.LogIfAclsTampered((FileSystemInfo) this.m_fileInfo.Directory))
|
|||
|
this.m_fileInfo.Directory.SetAccessControl(FileDataSource.CreateSecurityDescriptor<DirectorySecurity>());
|
|||
|
InfoCardTrace.Assert(this.m_shadowInfo.Directory.Exists, "m_shadowInfo directory should be same as main directory");
|
|||
|
this.OpenOrCreateHelper(this.m_fileInfo, out this.m_file);
|
|||
|
this.OpenOrCreateHelper(this.m_shadowInfo, out this.m_shadow);
|
|||
|
}
|
|||
|
catch (IOException ex)
|
|||
|
{
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(ex.Message));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void CheckReparsePoints()
|
|||
|
{
|
|||
|
using (new SystemIdentity(true))
|
|||
|
{
|
|||
|
for (DirectoryInfo directoryInfo = this.m_fileInfo.Directory; directoryInfo != null; directoryInfo = directoryInfo.Parent)
|
|||
|
{
|
|||
|
if (directoryInfo.Exists && (directoryInfo.Attributes & FileAttributes.ReparsePoint) != (FileAttributes) 0)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreNoReparsePointAllowed")));
|
|||
|
}
|
|||
|
if (Directory.Exists(this.m_fileInfo.FullName) && (this.m_fileInfo.Attributes & FileAttributes.ReparsePoint) != (FileAttributes) 0)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreNoReparsePointAllowed")));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ValidateDirectoryAccess()
|
|||
|
{
|
|||
|
InfoCardTrace.Assert(!WindowsIdentity.GetCurrent().IsSystem, "Should not be running as system");
|
|||
|
IdentityReference identityReference = WindowsIdentity.GetCurrent().User.Translate(typeof (NTAccount));
|
|||
|
bool flag = false;
|
|||
|
DirectoryInfo parent = this.m_fileInfo.Directory.Parent;
|
|||
|
if (parent.Exists)
|
|||
|
{
|
|||
|
foreach (FileSystemAccessRule accessRule in (ReadOnlyCollectionBase) parent.GetAccessControl().GetAccessRules(true, true, typeof (NTAccount)))
|
|||
|
{
|
|||
|
if (accessRule.IdentityReference == identityReference && accessRule.FileSystemRights == FileSystemRights.FullControl && accessRule.AccessControlType == AccessControlType.Allow)
|
|||
|
{
|
|||
|
flag = true;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (!flag)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreInvalidDataFilePath")));
|
|||
|
}
|
|||
|
|
|||
|
private void OpenOrCreateHelper(FileInfo theFile, out FileStream fileStream)
|
|||
|
{
|
|||
|
InfoCardTrace.Assert(WindowsIdentity.GetCurrent().IsSystem, "Should be running as system");
|
|||
|
if (!File.Exists(theFile.FullName))
|
|||
|
{
|
|||
|
fileStream = FileDataSource.ResilientOpen(theFile, FileMode.CreateNew, FileAccess.ReadWrite);
|
|||
|
theFile.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed;
|
|||
|
theFile.SetAccessControl(FileDataSource.CreateSecurityDescriptor<FileSecurity>());
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if (NativeMcppMethods.PathSupportsPersistedSecurity(this.m_fileInfo.Directory.FullName) && this.LogIfAclsTampered((FileSystemInfo) theFile))
|
|||
|
{
|
|||
|
theFile.SetAccessControl(FileDataSource.CreateSecurityDescriptor<FileSecurity>());
|
|||
|
theFile.Attributes |= FileAttributes.Hidden | FileAttributes.NotContentIndexed;
|
|||
|
}
|
|||
|
fileStream = FileDataSource.ResilientOpen(theFile, FileMode.Open, FileAccess.ReadWrite);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected virtual void OnSwapFileWithShadow()
|
|||
|
{
|
|||
|
using (new SystemIdentity(true))
|
|||
|
{
|
|||
|
string fullName = this.m_fileInfo.FullName;
|
|||
|
FileDataSource.ResilientDelete(this.m_fileInfo);
|
|||
|
FileDataSource.ResilientMove(this.m_shadowInfo, this.m_fileInfo);
|
|||
|
this.m_fileInfo = new FileInfo(fullName);
|
|||
|
this.m_shadowInfo = new FileInfo(fullName + ".shadow");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected internal override void OnClose()
|
|||
|
{
|
|||
|
this.ThrowIfDisposed();
|
|||
|
if (this.m_data != null)
|
|||
|
{
|
|||
|
this.m_data.Close();
|
|||
|
this.m_data = (IndexedDataBuffer) null;
|
|||
|
}
|
|||
|
this.m_indexes.Close();
|
|||
|
this.CloseFiles();
|
|||
|
this.m_provider.Dispose();
|
|||
|
}
|
|||
|
|
|||
|
protected internal override DataRow ReadRow(int localId, QueryDetails details)
|
|||
|
{
|
|||
|
DataRow row = (DataRow) null;
|
|||
|
if (QueryDetails.Header == (details & QueryDetails.Header))
|
|||
|
{
|
|||
|
row = this.m_data.CreateDataRow(localId);
|
|||
|
if (QueryDetails.DataBlob == (details & QueryDetails.DataBlob))
|
|||
|
{
|
|||
|
byte[] iv = this.AllocateIvBuffer();
|
|||
|
this.m_data.CopyIVFromObject(localId, iv, 0);
|
|||
|
using (Stream streamForObjectData = this.m_data.GetStreamForObjectData(localId))
|
|||
|
{
|
|||
|
using (MemoryStream output = new MemoryStream((int) streamForObjectData.Length))
|
|||
|
{
|
|||
|
this.DecryptData(iv, streamForObjectData, (Stream) output);
|
|||
|
row.SetDataField(output.ToArray());
|
|||
|
byte[] buffer = output.GetBuffer();
|
|||
|
Array.Clear((Array) buffer, 0, buffer.Length);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if (QueryDetails.IndexData == (details & QueryDetails.IndexData))
|
|||
|
this.m_indexes.PopulateRowIndexBuffer(row);
|
|||
|
}
|
|||
|
return row;
|
|||
|
}
|
|||
|
|
|||
|
protected internal override bool SingleMatch(QueryParameter match, LocalIdCollection localIds)
|
|||
|
{
|
|||
|
this.ThrowIfDisposed();
|
|||
|
this.ThrowIfNotLoaded();
|
|||
|
if (localIds == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (localIds));
|
|||
|
if (match == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (match));
|
|||
|
if (string.IsNullOrEmpty(match.IndexName))
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentException(SR.GetString("StoreDataSourceInvalidIndexName", (object) match.IndexName), nameof (match)));
|
|||
|
bool flag = false;
|
|||
|
try
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
this.m_lock.AcquireReaderLock(0);
|
|||
|
flag = true;
|
|||
|
}
|
|||
|
return this.m_indexes.Match(match, localIds);
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
if (flag)
|
|||
|
this.m_lock.ReleaseReaderLock();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected internal override void OnBeginTransaction()
|
|||
|
{
|
|||
|
InfoCardTrace.Assert(!this.m_currentTransactionDirty, "m_currentTransactionDirty should have been set to false before beginning a transaction");
|
|||
|
base.OnBeginTransaction();
|
|||
|
}
|
|||
|
|
|||
|
protected internal override void OnRollbackTransaction()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
base.OnRollbackTransaction();
|
|||
|
this.LoadFrom((Stream) this.m_file);
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
this.m_currentTransactionDirty = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected internal override void OnCommitTransaction()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
base.OnCommitTransaction();
|
|||
|
if (!this.m_currentTransactionDirty)
|
|||
|
return;
|
|||
|
this.FlushToShadow();
|
|||
|
this.SwapFileWithShadow();
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
this.m_currentTransactionDirty = false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected internal override void WriteRow(DataRow row)
|
|||
|
{
|
|||
|
this.ThrowIfDisposed();
|
|||
|
this.ThrowIfNotLoaded();
|
|||
|
this.ThrowIfWriteLockNotHeld();
|
|||
|
if (row == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (row));
|
|||
|
bool flag = false;
|
|||
|
try
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
this.m_lock.AcquireWriterLock(0);
|
|||
|
flag = true;
|
|||
|
}
|
|||
|
using (MemoryStream output = new MemoryStream())
|
|||
|
{
|
|||
|
this.m_encAlg.GenerateIV();
|
|||
|
byte[] iv = this.m_encAlg.IV;
|
|||
|
using (MemoryStream input = new MemoryStream(row.GetDataField()))
|
|||
|
{
|
|||
|
this.EncryptData(iv, (Stream) input, (Stream) output);
|
|||
|
int localId = this.m_data.WriteObject(row.LocalId, iv, output.ToArray(), row.ObjectType, row.LastChange, row.GlobalId);
|
|||
|
this.m_indexes.SetValuesForId(localId, row.IndexBuffer, true);
|
|||
|
row.SourceId = this.SourceId;
|
|||
|
row.InstanceId = this.InstanceId;
|
|||
|
row.LocalId = localId;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
if (flag)
|
|||
|
this.m_lock.ReleaseWriterLock();
|
|||
|
}
|
|||
|
this.m_currentTransactionDirty = true;
|
|||
|
}
|
|||
|
|
|||
|
protected internal override void RemoveObject(int id)
|
|||
|
{
|
|||
|
if ((uint) id > (uint) (this.m_data.Index.Length / 4 - 1))
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new ArgumentOutOfRangeException(nameof (id), (object) id, SR.GetString("StoreDataSourceIdOutOfRange")));
|
|||
|
bool flag = false;
|
|||
|
try
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
this.m_lock.AcquireWriterLock(0);
|
|||
|
flag = true;
|
|||
|
}
|
|||
|
this.m_data.RemoveObject(id);
|
|||
|
this.m_indexes.RemoveAllValuesForId(id);
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
if (flag)
|
|||
|
this.m_lock.ReleaseWriterLock();
|
|||
|
}
|
|||
|
this.m_currentTransactionDirty = true;
|
|||
|
}
|
|||
|
|
|||
|
private void ProtectKey()
|
|||
|
{
|
|||
|
if (this.m_keyProtected)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreKeyAlreadyProtected")));
|
|||
|
ProtectedMemory.Protect(this.m_key, MemoryProtectionScope.SameProcess);
|
|||
|
this.m_keyProtected = true;
|
|||
|
}
|
|||
|
|
|||
|
private void UnprotectKey()
|
|||
|
{
|
|||
|
if (!this.m_keyProtected)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreKeyNotAlreadyProtected")));
|
|||
|
ProtectedMemory.Unprotect(this.m_key, MemoryProtectionScope.SameProcess);
|
|||
|
this.m_keyProtected = false;
|
|||
|
}
|
|||
|
|
|||
|
private unsafe void DecryptData(byte[] iv, Stream input, Stream output)
|
|||
|
{
|
|||
|
InfoCardTrace.Assert(input is MemoryStream, "Invalid stream type");
|
|||
|
if (iv == null || iv.Length == 0)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (iv));
|
|||
|
if (input == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input));
|
|||
|
if (output == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (output));
|
|||
|
using (SafeCryptoKey safeCryptoKey = new SafeCryptoKey(this.m_provider, this.m_key, iv))
|
|||
|
{
|
|||
|
byte[] buffer = new byte[input.Length];
|
|||
|
input.Seek(0L, SeekOrigin.Begin);
|
|||
|
input.Read(buffer, 0, (int) input.Length);
|
|||
|
uint length = (uint) buffer.Length;
|
|||
|
fixed (byte* data = &buffer[0])
|
|||
|
{
|
|||
|
if (!NativeMethods.CryptDecrypt(safeCryptoKey.Handle, IntPtr.Zero, 1U, 0U, (IntPtr) (void*) data, ref length))
|
|||
|
{
|
|||
|
Exception e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
|
|||
|
Array.Clear((Array) buffer, 0, buffer.Length);
|
|||
|
InfoCardTrace.TraceAndLogException(e);
|
|||
|
throw InfoCardTrace.ThrowHelperError(e);
|
|||
|
}
|
|||
|
}
|
|||
|
output.Write(buffer, 0, (int) length);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private unsafe void EncryptData(byte[] iv, Stream input, Stream output)
|
|||
|
{
|
|||
|
if (iv == null || iv.Length == 0)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (iv));
|
|||
|
if (input == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input));
|
|||
|
if (output == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (output));
|
|||
|
using (SafeCryptoKey safeCryptoKey = new SafeCryptoKey(this.m_provider, this.m_key, iv))
|
|||
|
{
|
|||
|
byte[] buffer = new byte[input.Length + (long) this.m_key.Length];
|
|||
|
input.Seek(0L, SeekOrigin.Begin);
|
|||
|
input.Read(buffer, 0, (int) input.Length);
|
|||
|
uint length = (uint) input.Length;
|
|||
|
fixed (byte* data = &buffer[0])
|
|||
|
{
|
|||
|
if (!NativeMethods.CryptEncrypt(safeCryptoKey.Handle, IntPtr.Zero, 1U, 0U, (IntPtr) (void*) data, ref length, (uint) buffer.Length))
|
|||
|
{
|
|||
|
Exception e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
|
|||
|
InfoCardTrace.TraceAndLogException(e);
|
|||
|
throw InfoCardTrace.ThrowHelperError(e);
|
|||
|
}
|
|||
|
}
|
|||
|
output.Write(buffer, 0, (int) length);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private unsafe void CreateEmptyStore()
|
|||
|
{
|
|||
|
this.m_data = new IndexedDataBuffer(new byte[80], new byte[2048], 0, (DataSource) this);
|
|||
|
this.m_encAlg.GenerateKey();
|
|||
|
this.m_key = new byte[this.m_encAlg.Key.Length];
|
|||
|
Array.Copy((Array) this.m_encAlg.Key, 0, (Array) this.m_key, 0, this.m_encAlg.Key.Length);
|
|||
|
this.m_encAlg.GenerateKey();
|
|||
|
this.m_keyProtected = false;
|
|||
|
this.ProtectKey();
|
|||
|
this.m_header = new byte[this.GetTotalHeaderSize()];
|
|||
|
fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
|
|||
|
((EncryptedFileStoreHeader*) numPtr)->Version = 12U;
|
|||
|
this.EncryptAndSaveDPAPIKeyToHeader();
|
|||
|
}
|
|||
|
|
|||
|
private void FlushToShadow() => this.FlushToStream((Stream) this.m_shadow);
|
|||
|
|
|||
|
private int GetTotalHeaderSize() => sizeof (EncryptedFileStoreHeader) + this.GetTotalSignatureSize();
|
|||
|
|
|||
|
private int GetOffsetToEncryptedFileHeader() => this.m_variableSignatureLength + 4;
|
|||
|
|
|||
|
private int GetTotalSignatureSize() => this.GetOffsetToEncryptedFileHeader();
|
|||
|
|
|||
|
private long GetRequiredFileSize()
|
|||
|
{
|
|||
|
long num = Convert.ToInt64(this.GetTotalHeaderSize()) + Convert.ToInt64(this.m_encryptedKey.Length) + Convert.ToInt64(this.m_data.DataLength) + Convert.ToInt64(this.m_data.Index.Length + 4);
|
|||
|
foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys)
|
|||
|
{
|
|||
|
byte[] buffer = ((SecondaryIndex) this.m_indexes.InnerIndexes[(object) key]).GetBuffer();
|
|||
|
num += Convert.ToInt64(8 + buffer.Length);
|
|||
|
}
|
|||
|
return num + num / 20L;
|
|||
|
}
|
|||
|
|
|||
|
private unsafe void FlushToStream(Stream stream)
|
|||
|
{
|
|||
|
if (stream == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (stream));
|
|||
|
stream.SetLength(this.GetRequiredFileSize());
|
|||
|
BinaryWriter binaryWriter1 = new BinaryWriter(stream);
|
|||
|
this.m_encAlg.GenerateIV();
|
|||
|
byte[] iv = this.m_encAlg.IV;
|
|||
|
int dataLength = this.m_data.DataLength;
|
|||
|
stream.Seek((long) this.GetTotalHeaderSize(), SeekOrigin.Begin);
|
|||
|
binaryWriter1.Write(this.m_encryptedKey);
|
|||
|
binaryWriter1.Write(iv);
|
|||
|
long position = stream.Position;
|
|||
|
using (BinaryWriter binaryWriter2 = new BinaryWriter((Stream) new MemoryStream()))
|
|||
|
{
|
|||
|
binaryWriter2.Write(this.m_data.Index.Length / 4);
|
|||
|
binaryWriter2.Write(this.m_data.Index);
|
|||
|
binaryWriter2.Write(this.m_indexes.Count);
|
|||
|
foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys)
|
|||
|
{
|
|||
|
SecondaryIndex innerIndex = (SecondaryIndex) this.m_indexes.InnerIndexes[(object) key];
|
|||
|
int lastIndex = innerIndex.LastIndex;
|
|||
|
binaryWriter2.Write(lastIndex);
|
|||
|
int initialSize = SecondaryIndexDefinition.GetByName(key).InitialSize;
|
|||
|
if (lastIndex + 1 < initialSize)
|
|||
|
{
|
|||
|
binaryWriter2.Write(initialSize);
|
|||
|
InfoCardTrace.Assert(initialSize * sizeof (SecondaryIndexItem) <= innerIndex.GetBuffer().Length, "Buffer length is at least min capacity");
|
|||
|
binaryWriter2.Write(innerIndex.GetBuffer(), 0, initialSize * sizeof (SecondaryIndexItem));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
binaryWriter2.Write(lastIndex + 1);
|
|||
|
binaryWriter2.Write(innerIndex.GetBuffer(), 0, (lastIndex + 1) * sizeof (SecondaryIndexItem));
|
|||
|
}
|
|||
|
}
|
|||
|
binaryWriter2.Flush();
|
|||
|
binaryWriter2.Seek(0, SeekOrigin.Begin);
|
|||
|
this.EncryptData(iv, binaryWriter2.BaseStream, binaryWriter1.BaseStream);
|
|||
|
}
|
|||
|
int int32 = Convert.ToInt32(stream.Position - position);
|
|||
|
int num = int32 + this.m_data.DataLength + this.GetTotalHeaderSize() + iv.Length + this.m_encryptedKey.Length;
|
|||
|
binaryWriter1.Write(this.m_data.Data, 0, this.m_data.DataLength);
|
|||
|
stream.Seek(0L, SeekOrigin.Begin);
|
|||
|
binaryWriter1.Flush();
|
|||
|
fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
|
|||
|
{
|
|||
|
((EncryptedFileStoreHeader*) numPtr)->DataSize = dataLength;
|
|||
|
((EncryptedFileStoreHeader*) numPtr)->Version = 12U;
|
|||
|
((EncryptedFileStoreHeader*) numPtr)->Size = num;
|
|||
|
((EncryptedFileStoreHeader*) numPtr)->IndexSize = int32;
|
|||
|
}
|
|||
|
binaryWriter1.Write(this.m_header);
|
|||
|
stream.SetLength(Convert.ToInt64(num));
|
|||
|
binaryWriter1.Flush();
|
|||
|
this.SignStream(stream);
|
|||
|
}
|
|||
|
|
|||
|
private unsafe void SignStream(Stream input)
|
|||
|
{
|
|||
|
long offset = input != null ? input.Position : throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input));
|
|||
|
this.m_encAlg.GenerateIV();
|
|||
|
byte[] sourceArray = this.SignDigest(this.m_encAlg.IV, this.CreateStreamDigest(input));
|
|||
|
byte[] numArray = new byte[this.GetTotalSignatureSize()];
|
|||
|
fixed (byte* numPtr = &numArray[0])
|
|||
|
((SignatureHeader*) numPtr)->SignatureSize = this.m_variableSignatureLength;
|
|||
|
Array.Copy((Array) sourceArray, 0, (Array) numArray, 4, sourceArray.Length);
|
|||
|
input.Seek(0L, SeekOrigin.Begin);
|
|||
|
input.Write(numArray, 0, numArray.Length);
|
|||
|
InfoCardTrace.Assert(this.m_variableSignatureLength >= sourceArray.Length, "Generated signature should be less than signature length");
|
|||
|
input.Seek(offset, SeekOrigin.Begin);
|
|||
|
}
|
|||
|
|
|||
|
private byte[] CreateStreamDigest(Stream input)
|
|||
|
{
|
|||
|
input.Seek((long) this.GetOffsetToEncryptedFileHeader(), SeekOrigin.Begin);
|
|||
|
byte[] data = new byte[Convert.ToInt32((input.Length / 4096L + 1L) * (long) HashUtility.HashBufferLength)];
|
|||
|
int dataIndex = 0;
|
|||
|
byte[] numArray = new byte[4096];
|
|||
|
int dataToHashSize;
|
|||
|
do
|
|||
|
{
|
|||
|
dataToHashSize = input.Read(numArray, 0, numArray.Length);
|
|||
|
if (dataToHashSize > 0)
|
|||
|
{
|
|||
|
HashUtility.SetHashValue(data, dataIndex, numArray, 0, dataToHashSize);
|
|||
|
dataIndex += HashUtility.HashBufferLength;
|
|||
|
}
|
|||
|
}
|
|||
|
while (dataToHashSize == numArray.Length);
|
|||
|
return data;
|
|||
|
}
|
|||
|
|
|||
|
private byte[] SignDigest(byte[] iv, byte[] digest)
|
|||
|
{
|
|||
|
byte[] destinationArray = new byte[this.m_variableSignatureLength];
|
|||
|
using (MemoryStream input = new MemoryStream(digest))
|
|||
|
{
|
|||
|
using (MemoryStream output = new MemoryStream(digest.Length))
|
|||
|
{
|
|||
|
this.EncryptData(iv, (Stream) input, (Stream) output);
|
|||
|
Array.Copy((Array) output.GetBuffer(), Convert.ToInt32(output.Position - 1L) - iv.Length, (Array) destinationArray, 0, iv.Length);
|
|||
|
Array.Copy((Array) iv, 0, (Array) destinationArray, iv.Length, iv.Length);
|
|||
|
return destinationArray;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ValidateSignature(Stream input)
|
|||
|
{
|
|||
|
long offset = input != null ? input.Position : throw InfoCardTrace.ThrowHelperArgumentNull(nameof (input));
|
|||
|
byte[] buffer = new byte[this.m_variableSignatureLength];
|
|||
|
byte[] numArray1 = this.AllocateIvBuffer();
|
|||
|
input.Seek(20L, SeekOrigin.Begin);
|
|||
|
input.Read(numArray1, 0, numArray1.Length);
|
|||
|
byte[] numArray2 = this.SignDigest(numArray1, this.CreateStreamDigest(input));
|
|||
|
input.Seek(4L, SeekOrigin.Begin);
|
|||
|
input.Read(buffer, 0, buffer.Length);
|
|||
|
for (int index = 0; index < buffer.Length; ++index)
|
|||
|
{
|
|||
|
if ((int) buffer[index] != (int) numArray2[index])
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new CorruptStoreException(SR.GetString("StoreSignatureNotValid")));
|
|||
|
}
|
|||
|
input.Seek(offset, SeekOrigin.Begin);
|
|||
|
}
|
|||
|
|
|||
|
protected unsafe void LoadFrom(Stream stream)
|
|||
|
{
|
|||
|
if (stream == null)
|
|||
|
throw InfoCardTrace.ThrowHelperArgumentNull(nameof (stream));
|
|||
|
stream.Seek(0L, SeekOrigin.Begin);
|
|||
|
BinaryReader binaryReader1 = (BinaryReader) new InfoCardBinaryReader(stream);
|
|||
|
this.m_header = new byte[this.GetTotalHeaderSize()];
|
|||
|
binaryReader1.Read(this.m_header, 0, this.m_header.Length);
|
|||
|
fixed (byte* numPtr1 = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
|
|||
|
{
|
|||
|
if (11U != ((EncryptedFileStoreHeader*) numPtr1)->Version && 12U != ((EncryptedFileStoreHeader*) numPtr1)->Version)
|
|||
|
{
|
|||
|
CorruptStoreException e = new CorruptStoreException(SR.GetString("StoreVersionNotSupported", (object) ((EncryptedFileStoreHeader*) numPtr1)->Version));
|
|||
|
InfoCardTrace.TraceAndLogException((Exception) e);
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) e);
|
|||
|
}
|
|||
|
if (12U == ((EncryptedFileStoreHeader*) numPtr1)->Version)
|
|||
|
{
|
|||
|
this.m_encryptedKey = new byte[((EncryptedFileStoreHeader*) numPtr1)->KeyBlockV2.KeyDataSize];
|
|||
|
binaryReader1.Read(this.m_encryptedKey, 0, ((EncryptedFileStoreHeader*) numPtr1)->KeyBlockV2.KeyDataSize);
|
|||
|
}
|
|||
|
// ISSUE: __unpin statement
|
|||
|
__unpin(numPtr1);
|
|||
|
fixed (byte* numPtr2 = &this.m_header[0])
|
|||
|
{
|
|||
|
if (this.m_variableSignatureLength != ((SignatureHeader*) numPtr2)->SignatureSize)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new CorruptStoreException(SR.GetString("StoreSignatureNotValid")));
|
|||
|
}
|
|||
|
this.ObtainDataKeyFromHeader();
|
|||
|
this.ValidateSignature(stream);
|
|||
|
fixed (byte* numPtr3 = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
|
|||
|
{
|
|||
|
byte[] numArray = this.AllocateIvBuffer();
|
|||
|
byte[] masterIndex;
|
|||
|
using (MemoryStream output = new MemoryStream())
|
|||
|
{
|
|||
|
binaryReader1.Read(numArray, 0, numArray.Length);
|
|||
|
byte[] buffer1 = binaryReader1.ReadBytes(((EncryptedFileStoreHeader*) numPtr3)->IndexSize);
|
|||
|
using (MemoryStream input = new MemoryStream(buffer1))
|
|||
|
{
|
|||
|
this.DecryptData(numArray, (Stream) input, (Stream) output);
|
|||
|
Array.Clear((Array) buffer1, 0, buffer1.Length);
|
|||
|
}
|
|||
|
output.Seek(0L, SeekOrigin.Begin);
|
|||
|
BinaryReader binaryReader2 = (BinaryReader) new InfoCardBinaryReader((Stream) output);
|
|||
|
int num1 = binaryReader2.ReadInt32();
|
|||
|
InfoCardTrace.Assert(num1 > 0, "MasterIndexCount Invalid");
|
|||
|
masterIndex = binaryReader2.ReadBytes(num1 * 4);
|
|||
|
InfoCardTrace.Assert((uint) binaryReader2.ReadInt32() <= (uint) this.m_indexes.Count, "SecondaryIndexCount Invalid");
|
|||
|
foreach (string key in (IEnumerable) this.m_indexes.InnerIndexes.Keys)
|
|||
|
{
|
|||
|
int lastIndex = binaryReader2.ReadInt32();
|
|||
|
int num2 = binaryReader2.ReadInt32();
|
|||
|
byte[] buffer2 = new byte[Utility.CalculateIncreaseByPercent(num2 * sizeof (SecondaryIndexItem), sizeof (SecondaryIndexItem), SecondaryIndexDefinition.GetByName(key).GrowthFactor)];
|
|||
|
binaryReader2.Read(buffer2, 0, num2 * sizeof (SecondaryIndexItem));
|
|||
|
this.m_indexes.SetBuffer(key, buffer2, lastIndex);
|
|||
|
}
|
|||
|
}
|
|||
|
using (MemoryStream memoryStream = new MemoryStream(Utility.CalculateIncreaseByPercent(Convert.ToInt32(binaryReader1.BaseStream.Length - binaryReader1.BaseStream.Position), 1, 5)))
|
|||
|
{
|
|||
|
byte[] buffer3 = new byte[256];
|
|||
|
int num = 0;
|
|||
|
int count;
|
|||
|
do
|
|||
|
{
|
|||
|
count = binaryReader1.Read(buffer3, 0, buffer3.Length);
|
|||
|
memoryStream.Write(buffer3, 0, count);
|
|||
|
num += count;
|
|||
|
}
|
|||
|
while (count == buffer3.Length);
|
|||
|
byte[] buffer4 = memoryStream.GetBuffer();
|
|||
|
if (num == 0)
|
|||
|
buffer4 = new byte[2048];
|
|||
|
this.m_data = new IndexedDataBuffer(masterIndex, buffer4, ((EncryptedFileStoreHeader*) numPtr3)->DataSize, (DataSource) this);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
protected virtual void SwapFileWithShadow()
|
|||
|
{
|
|||
|
this.CloseFiles();
|
|||
|
this.OnSwapFileWithShadow();
|
|||
|
try
|
|||
|
{
|
|||
|
this.CreateDirAndFiles();
|
|||
|
}
|
|||
|
catch
|
|||
|
{
|
|||
|
this.CloseFiles();
|
|||
|
throw;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private unsafe void EncryptAndSaveDPAPIKeyToHeader()
|
|||
|
{
|
|||
|
DataBlob dataBlob1 = new DataBlob();
|
|||
|
DataBlob dataBlob2 = new DataBlob();
|
|||
|
byte[] numArray = new byte[32 + HashUtility.HashBufferLength];
|
|||
|
this.UnprotectKey();
|
|||
|
try
|
|||
|
{
|
|||
|
Array.Copy((Array) this.m_key, 0, (Array) numArray, 0, 32);
|
|||
|
HashUtility.SetHashValue(numArray, 32, this.m_key, 0, 32);
|
|||
|
fixed (byte* numPtr1 = &numArray[0])
|
|||
|
{
|
|||
|
DataBlob dataBlob3;
|
|||
|
dataBlob3.pbData = new IntPtr((void*) numPtr1);
|
|||
|
dataBlob3.cbData = numArray.Length;
|
|||
|
try
|
|||
|
{
|
|||
|
if (!NativeMethods.CryptProtectData(new IntPtr((void*) &dataBlob3), (string) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 65, new IntPtr((void*) &dataBlob1)))
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptProtectDataFailed")));
|
|||
|
using (new SystemIdentity(true))
|
|||
|
{
|
|||
|
if (!NativeMethods.CryptProtectData(new IntPtr((void*) &dataBlob1), (string) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 65, new IntPtr((void*) &dataBlob2)))
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptProtectDataAsSystemFailed")));
|
|||
|
}
|
|||
|
fixed (byte* numPtr2 = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
|
|||
|
{
|
|||
|
((EncryptedFileStoreHeader*) numPtr2)->KeyBlockV2.KeyDataOffset = 0;
|
|||
|
((EncryptedFileStoreHeader*) numPtr2)->KeyBlockV2.KeyDataSize = dataBlob2.cbData;
|
|||
|
this.m_encryptedKey = new byte[dataBlob2.cbData];
|
|||
|
for (int index = 0; index < dataBlob2.cbData; ++index)
|
|||
|
this.m_encryptedKey[index] = *(byte*) ((IntPtr) dataBlob2.pbData.ToPointer() + index);
|
|||
|
}
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
Exception e = (Exception) null;
|
|||
|
if (IntPtr.Zero != dataBlob1.pbData)
|
|||
|
{
|
|||
|
Utility.ClearUnsafeMemory(dataBlob1.pbData, dataBlob1.cbData);
|
|||
|
if (IntPtr.Zero != NativeMethods.LocalFree(dataBlob1.pbData))
|
|||
|
e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
|
|||
|
}
|
|||
|
if (IntPtr.Zero != dataBlob2.pbData)
|
|||
|
{
|
|||
|
Utility.ClearUnsafeMemory(dataBlob2.pbData, dataBlob2.cbData);
|
|||
|
if (IntPtr.Zero != NativeMethods.LocalFree(dataBlob2.pbData))
|
|||
|
e = (Exception) new Win32Exception(Marshal.GetLastWin32Error());
|
|||
|
}
|
|||
|
if (e != null)
|
|||
|
throw InfoCardTrace.ThrowHelperError(e);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
this.ProtectKey();
|
|||
|
Array.Clear((Array) numArray, 0, numArray.Length);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private void ObtainDataKeyFromHeader()
|
|||
|
{
|
|||
|
try
|
|||
|
{
|
|||
|
this.m_key = this.TryObtainDataKeyFromDPAPI() ?? throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreUnableToGetStoreKeyFromDPAPI")));
|
|||
|
this.m_keyProtected = false;
|
|||
|
this.ProtectKey();
|
|||
|
}
|
|||
|
catch (Exception ex)
|
|||
|
{
|
|||
|
if (!InfoCardTrace.IsFatal(ex))
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidStoreProtectionKeyException());
|
|||
|
throw;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private unsafe byte[] TryObtainDataKeyFromDPAPI()
|
|||
|
{
|
|||
|
DataBlob dataBlob1 = new DataBlob();
|
|||
|
DataBlob dataBlob2 = new DataBlob();
|
|||
|
fixed (byte* numPtr = &this.m_header[this.GetOffsetToEncryptedFileHeader()])
|
|||
|
{
|
|||
|
if (11U == ((EncryptedFileStoreHeader*) numPtr)->Version && ((EncryptedFileStoreHeader*) numPtr)->KeyBlock.KeyType != 0)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreFileNotProtectedWithDPAPI")));
|
|||
|
byte[] dataKeyFromDpapi = (byte[]) null;
|
|||
|
GCHandle gcHandle = new GCHandle();
|
|||
|
try
|
|||
|
{
|
|||
|
DataBlob dataBlob3;
|
|||
|
if (((EncryptedFileStoreHeader*) numPtr)->Version == 12U)
|
|||
|
{
|
|||
|
gcHandle = GCHandle.Alloc((object) this.m_encryptedKey, GCHandleType.Pinned);
|
|||
|
dataBlob3.pbData = gcHandle.AddrOfPinnedObject();
|
|||
|
dataBlob3.cbData = ((EncryptedFileStoreHeader*) numPtr)->KeyBlockV2.KeyDataSize;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
dataBlob3.pbData = new IntPtr((void*) &((EncryptedFileStoreHeader*) numPtr)->KeyBlock.EncryptedKey);
|
|||
|
dataBlob3.cbData = ((EncryptedFileStoreHeader*) numPtr)->KeyBlock.EncryptedKeySize;
|
|||
|
((EncryptedFileStoreHeader*) numPtr)->KeyBlockV2.KeyDataOffset = 0;
|
|||
|
((EncryptedFileStoreHeader*) numPtr)->KeyBlockV2.KeyDataSize = dataBlob3.cbData;
|
|||
|
this.m_encryptedKey = new byte[dataBlob3.cbData];
|
|||
|
for (int index = 0; index < dataBlob3.cbData; ++index)
|
|||
|
this.m_encryptedKey[index] = *(byte*) ((IntPtr) dataBlob3.pbData.ToPointer() + index);
|
|||
|
}
|
|||
|
using (new SystemIdentity(true))
|
|||
|
{
|
|||
|
if (!NativeMethods.CryptUnprotectData(new IntPtr((void*) &dataBlob3), (StringBuilder) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, new IntPtr((void*) &dataBlob2)))
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptUnprotectDataAsSystemFailed")));
|
|||
|
}
|
|||
|
if (!NativeMethods.CryptUnprotectData(new IntPtr((void*) &dataBlob2), (StringBuilder) null, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 1, new IntPtr((void*) &dataBlob1)))
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new Win32Exception(Marshal.GetLastWin32Error(), SR.GetString("StoreCryptUnprotectDataFailed")));
|
|||
|
InfoCardTrace.Assert(dataBlob1.cbData == 32 + HashUtility.HashBufferLength, "The data size returned by CryptUnprotectData is invalid or corrupt.");
|
|||
|
dataKeyFromDpapi = new byte[32];
|
|||
|
Marshal.Copy(dataBlob1.pbData, dataKeyFromDpapi, 0, 32);
|
|||
|
byte[] data = new byte[HashUtility.HashBufferLength];
|
|||
|
HashUtility.SetHashValue(data, 0, dataKeyFromDpapi, 0, 32);
|
|||
|
for (int index = 0; index < data.Length; ++index)
|
|||
|
{
|
|||
|
if ((int) data[index] != (int) *(byte*) ((IntPtr) dataBlob1.pbData.ToPointer() + (32 + index)))
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new InvalidOperationException(SR.GetString("StoreDecryptedKeyIsNotValid")));
|
|||
|
}
|
|||
|
return dataKeyFromDpapi;
|
|||
|
}
|
|||
|
catch
|
|||
|
{
|
|||
|
if (dataKeyFromDpapi != null)
|
|||
|
Array.Clear((Array) dataKeyFromDpapi, 0, dataKeyFromDpapi.Length);
|
|||
|
throw;
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
if (gcHandle.IsAllocated)
|
|||
|
gcHandle.Free();
|
|||
|
if (IntPtr.Zero != dataBlob2.pbData)
|
|||
|
{
|
|||
|
Utility.ClearUnsafeMemory(dataBlob2.pbData, dataBlob2.cbData);
|
|||
|
NativeMethods.LocalFree(dataBlob2.pbData);
|
|||
|
}
|
|||
|
if (IntPtr.Zero != dataBlob1.pbData)
|
|||
|
{
|
|||
|
Utility.ClearUnsafeMemory(dataBlob1.pbData, dataBlob1.cbData);
|
|||
|
NativeMethods.LocalFree(dataBlob1.pbData);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private bool LogIfAclsTampered(FileSystemInfo fileSysInfo)
|
|||
|
{
|
|||
|
bool condition = true;
|
|||
|
try
|
|||
|
{
|
|||
|
FileSystemSecurity accessControl;
|
|||
|
if (fileSysInfo is DirectoryInfo)
|
|||
|
{
|
|||
|
accessControl = (FileSystemSecurity) ((DirectoryInfo) fileSysInfo).GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
InfoCardTrace.Assert(fileSysInfo is FileInfo, "Only fileinfo possible");
|
|||
|
accessControl = (FileSystemSecurity) ((FileInfo) fileSysInfo).GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner);
|
|||
|
}
|
|||
|
condition = this.LogIfAclsTamperedHelper(accessControl);
|
|||
|
}
|
|||
|
catch (UnauthorizedAccessException ex)
|
|||
|
{
|
|||
|
InfoCardTrace.Assert(condition, "ACL must have been tampered with");
|
|||
|
}
|
|||
|
if (condition)
|
|||
|
InfoCardTrace.TraceAndLogException((Exception) new DataAccessException(SR.GetString("StoreAclsTamperedWith")));
|
|||
|
return condition;
|
|||
|
}
|
|||
|
|
|||
|
private bool LogIfAclsTamperedHelper(FileSystemSecurity fs)
|
|||
|
{
|
|||
|
if (SystemIdentity.LsaIdentityReference != fs.GetOwner(typeof (SecurityIdentifier)))
|
|||
|
return true;
|
|||
|
AuthorizationRuleCollection accessRules = fs.GetAccessRules(true, true, typeof (SecurityIdentifier));
|
|||
|
bool flag = fs is DirectorySecurity;
|
|||
|
foreach (FileSystemAccessRule systemAccessRule in (ReadOnlyCollectionBase) accessRules)
|
|||
|
{
|
|||
|
if ((!(SystemIdentity.LsaIdentityReference == systemAccessRule.IdentityReference) || FileSystemRights.FullControl != systemAccessRule.FileSystemRights || systemAccessRule.AccessControlType != AccessControlType.Allow) && (!flag || !((IdentityReference) FileDataSource.AdministratorSid == systemAccessRule.IdentityReference) || systemAccessRule.AccessControlType != AccessControlType.Allow || (FileSystemRights.ReadData | FileSystemRights.DeleteSubdirectoriesAndFiles | FileSystemRights.Synchronize) != systemAccessRule.FileSystemRights))
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
private static T CreateSecurityDescriptor<T>() where T : FileSystemSecurity, new()
|
|||
|
{
|
|||
|
T securityDescriptor = new T();
|
|||
|
securityDescriptor.SetOwner(SystemIdentity.LsaIdentityReference);
|
|||
|
foreach (FileSystemAccessRule accessRule in (ReadOnlyCollectionBase) securityDescriptor.GetAccessRules(true, true, typeof (SecurityIdentifier)))
|
|||
|
securityDescriptor.RemoveAccessRuleAll(accessRule);
|
|||
|
securityDescriptor.AddAccessRule(new FileSystemAccessRule(SystemIdentity.LsaIdentityReference, FileSystemRights.FullControl, InheritanceFlags.None, PropagationFlags.None, AccessControlType.Allow));
|
|||
|
if ((object) securityDescriptor is DirectorySecurity)
|
|||
|
securityDescriptor.AddAccessRule(new FileSystemAccessRule((IdentityReference) FileDataSource.AdministratorSid, FileSystemRights.ReadData | FileSystemRights.DeleteSubdirectoriesAndFiles, AccessControlType.Allow));
|
|||
|
securityDescriptor.SetAccessRuleProtection(true, false);
|
|||
|
return securityDescriptor;
|
|||
|
}
|
|||
|
|
|||
|
private void SetupProvider() => this.m_provider = SafeRsaProviderHandle.Construct();
|
|||
|
|
|||
|
private byte[] AllocateIvBuffer()
|
|||
|
{
|
|||
|
InfoCardTrace.Assert(16 == this.m_encAlg.IV.Length, "Must be equal");
|
|||
|
InfoCardTrace.Assert(16 == this.m_encAlg.IV.Length, "Must be equal");
|
|||
|
return new byte[this.m_encAlg.IV.Length];
|
|||
|
}
|
|||
|
|
|||
|
private static void ResilientDelete(FileInfo toDelete)
|
|||
|
{
|
|||
|
int millisecondsTimeout = 10;
|
|||
|
bool flag = true;
|
|||
|
Exception inner = (Exception) null;
|
|||
|
do
|
|||
|
{
|
|||
|
if (!flag)
|
|||
|
{
|
|||
|
Thread.Sleep(millisecondsTimeout);
|
|||
|
millisecondsTimeout *= 2;
|
|||
|
}
|
|||
|
try
|
|||
|
{
|
|||
|
toDelete.Delete();
|
|||
|
flag = true;
|
|||
|
}
|
|||
|
catch (IOException ex)
|
|||
|
{
|
|||
|
inner = (Exception) ex;
|
|||
|
flag = false;
|
|||
|
}
|
|||
|
}
|
|||
|
while (!flag && millisecondsTimeout <= 500);
|
|||
|
if (!flag)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreFileInUse"), inner));
|
|||
|
}
|
|||
|
|
|||
|
private static void ResilientMove(FileInfo fileFrom, FileInfo fileTo)
|
|||
|
{
|
|||
|
int millisecondsTimeout = 10;
|
|||
|
bool flag = true;
|
|||
|
do
|
|||
|
{
|
|||
|
if (!flag)
|
|||
|
{
|
|||
|
Thread.Sleep(millisecondsTimeout);
|
|||
|
millisecondsTimeout *= 2;
|
|||
|
}
|
|||
|
try
|
|||
|
{
|
|||
|
fileFrom.MoveTo(fileTo.FullName);
|
|||
|
flag = true;
|
|||
|
}
|
|||
|
catch (IOException ex)
|
|||
|
{
|
|||
|
flag = false;
|
|||
|
}
|
|||
|
}
|
|||
|
while (!flag && millisecondsTimeout <= 500);
|
|||
|
if (flag)
|
|||
|
return;
|
|||
|
InfoCardTrace.FailFast(SR.GetString("StoreFileInUse"));
|
|||
|
}
|
|||
|
|
|||
|
private static FileStream ResilientOpen(
|
|||
|
FileInfo toOpen,
|
|||
|
FileMode mode,
|
|||
|
FileAccess access)
|
|||
|
{
|
|||
|
int millisecondsTimeout = 10;
|
|||
|
bool flag = true;
|
|||
|
Exception inner = (Exception) null;
|
|||
|
FileStream fileStream = (FileStream) null;
|
|||
|
do
|
|||
|
{
|
|||
|
if (!flag)
|
|||
|
{
|
|||
|
Thread.Sleep(millisecondsTimeout);
|
|||
|
millisecondsTimeout *= 2;
|
|||
|
}
|
|||
|
try
|
|||
|
{
|
|||
|
fileStream = toOpen.Open(mode, access, FileShare.None);
|
|||
|
flag = true;
|
|||
|
}
|
|||
|
catch (IOException ex)
|
|||
|
{
|
|||
|
inner = (Exception) ex;
|
|||
|
flag = false;
|
|||
|
}
|
|||
|
}
|
|||
|
while (!flag && millisecondsTimeout <= 500);
|
|||
|
if (!flag)
|
|||
|
throw InfoCardTrace.ThrowHelperError((Exception) new DataAccessException(SR.GetString("StoreFileInUse"), inner));
|
|||
|
return fileStream;
|
|||
|
}
|
|||
|
|
|||
|
internal static SymmetricAlgorithm CreateEncryptionAlg()
|
|||
|
{
|
|||
|
RijndaelManaged encryptionAlg = new RijndaelManaged();
|
|||
|
encryptionAlg.Mode = CipherMode.CBC;
|
|||
|
encryptionAlg.KeySize = 256;
|
|||
|
encryptionAlg.BlockSize = 128;
|
|||
|
return (SymmetricAlgorithm) encryptionAlg;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|