DataProtection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / ManagedLibraries / Security / System / Security / Cryptography / DataProtection.cs / 1305376 / DataProtection.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// [....]
// 
 
//
// DataProtection.cs 
//
// 01/25/2003
//
 
namespace System.Security.Cryptography
{ 
    using Microsoft.Win32; 
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices; 
    using System.Runtime.ConstrainedExecution;
    using System.Security.Permissions;
    using System.Globalization;
 
    public enum DataProtectionScope {
        CurrentUser     = 0x00, 
        LocalMachine    = 0x01 
    }
 
    public enum MemoryProtectionScope {
        SameProcess     = 0x00,
        CrossProcess    = 0x01,
        SameLogon       = 0x02 
    }
 
    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] 
    public static class ProtectedData {
        [SecuritySafeCritical] 
        public static byte[] Protect (byte[] userData,
                                      byte[] optionalEntropy,
                                      DataProtectionScope scope) {
            if (userData == null) 
                throw new ArgumentNullException("userData");
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows) 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 

            GCHandle pbDataIn = new GCHandle(); 
            GCHandle pOptionalEntropy = new GCHandle();
            CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB();

            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                pbDataIn = GCHandle.Alloc(userData, GCHandleType.Pinned); 
                CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB(); 
                dataIn.cbData = (uint) userData.Length;
                dataIn.pbData = pbDataIn.AddrOfPinnedObject(); 
                CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB();
                if (optionalEntropy != null) {
                    pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);
                    entropy.cbData = (uint) optionalEntropy.Length; 
                    entropy.pbData = pOptionalEntropy.AddrOfPinnedObject();
                } 
                uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN; 
                if (scope == DataProtectionScope.LocalMachine)
                    dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE; 
                unsafe {
                    if (!CAPI.CryptProtectData(new IntPtr(&dataIn),
                                               String.Empty,
                                               new IntPtr(&entropy), 
                                               IntPtr.Zero,
                                               IntPtr.Zero, 
                                               dwFlags, 
                                               new IntPtr(&blob))) {
                        int lastWin32Error = Marshal.GetLastWin32Error(); 

                        // One of the most common reasons that DPAPI operations fail is that the user
                        // profile is not loaded (for instance in the case of impersonation or running in a
                        // service.  In those cases, throw an exception that provides more specific details 
                        // about what happened.
                        if (CAPI.ErrorMayBeCausedByUnloadedProfile(lastWin32Error)) { 
                            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_ProfileMayNotBeLoaded")); 
                        }
                        else { 
                            throw new CryptographicException(lastWin32Error);
                        }
                    }
                } 

                // In some cases, the API would fail due to OOM but simply return a null pointer. 
                if (blob.pbData == IntPtr.Zero) 
                    throw new OutOfMemoryException();
 
                byte[] encryptedData = new byte[(int) blob.cbData];
                Marshal.Copy(blob.pbData, encryptedData, 0, encryptedData.Length);

                return encryptedData; 
            }
            catch (EntryPointNotFoundException) { 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 
            }
            finally { 
                if (pbDataIn.IsAllocated)
                   pbDataIn.Free();
                if (pOptionalEntropy.IsAllocated)
                   pOptionalEntropy.Free(); 
                if (blob.pbData != IntPtr.Zero) {
                    CAPI.CAPISafe.ZeroMemory(blob.pbData, blob.cbData); 
                    CAPI.CAPISafe.LocalFree(blob.pbData); 
                }
            } 
        }

        [SecuritySafeCritical]
        public static byte[] Unprotect (byte[] encryptedData, 
                                        byte[] optionalEntropy,
                                        DataProtectionScope scope) { 
            if (encryptedData == null) 
                throw new ArgumentNullException("encryptedData");
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows) 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));

            GCHandle pbDataIn = new GCHandle();
            GCHandle pOptionalEntropy = new GCHandle(); 
            CAPI.CRYPTOAPI_BLOB userData = new CAPI.CRYPTOAPI_BLOB();
 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                pbDataIn = GCHandle.Alloc(encryptedData, GCHandleType.Pinned); 
                CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB();
                dataIn.cbData = (uint) encryptedData.Length;
                dataIn.pbData = pbDataIn.AddrOfPinnedObject();
                CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB(); 
                if (optionalEntropy != null) {
                    pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned); 
                    entropy.cbData = (uint) optionalEntropy.Length; 
                    entropy.pbData = pOptionalEntropy.AddrOfPinnedObject();
                } 
                uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN;
                if (scope == DataProtectionScope.LocalMachine)
                    dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE;
                unsafe { 
                    if (!CAPI.CryptUnprotectData(new IntPtr(&dataIn),
                                                 IntPtr.Zero, 
                                                 new IntPtr(&entropy), 
                                                 IntPtr.Zero,
                                                 IntPtr.Zero, 
                                                 dwFlags,
                                                 new IntPtr(&userData)))
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                } 

                // In some cases, the API would fail due to OOM but simply return a null pointer. 
                if (userData.pbData == IntPtr.Zero) 
                    throw new OutOfMemoryException();
 
                byte[] data = new byte[(int) userData.cbData];
                Marshal.Copy(userData.pbData, data, 0, data.Length);

                return data; 
            }
            catch (EntryPointNotFoundException) { 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 
            }
            finally { 
                if (pbDataIn.IsAllocated)
                   pbDataIn.Free();
                if (pOptionalEntropy.IsAllocated)
                   pOptionalEntropy.Free(); 
                if (userData.pbData != IntPtr.Zero) {
                    CAPI.CAPISafe.ZeroMemory(userData.pbData, userData.cbData); 
                    CAPI.CAPISafe.LocalFree(userData.pbData); 
                }
            } 
        }
    }

    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] 
    public static class ProtectedMemory {
        [SecuritySafeCritical] 
        public static void Protect (byte[] userData, 
                                    MemoryProtectionScope scope) {
            if (userData == null) 
                throw new ArgumentNullException("userData");
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows)
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));
 
            VerifyScope(scope);
 
            // The RtlEncryptMemory and RtlDecryptMemory functions are available on WinXP and publicly published 
            // in the ntsecapi.h header file as of Windows Server 2003.
            // The Rtl functions accept data in 8 byte increments, but we don't want applications to be able to make use of this, 
            // or else they're liable to break when the user upgrades.
            if ((userData.Length == 0) || (userData.Length % CAPI.CRYPTPROTECTMEMORY_BLOCK_SIZE != 0))
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_InvalidMemoryLength"));
 
            uint dwFlags = (uint) scope;
            try { 
                // RtlEncryptMemory return an NTSTATUS 
                int status = CAPI.SystemFunction040(userData,
                                                    (uint) userData.Length, 
                                                    dwFlags);
                if (status < 0) // non-negative numbers indicate success
                    throw new CryptographicException(CAPI.CAPISafe.LsaNtStatusToWinError(status));
            } 
            catch (EntryPointNotFoundException) {
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 
            } 
        }
 
        [SecuritySafeCritical]
        public static void Unprotect (byte[] encryptedData,
                                      MemoryProtectionScope scope) {
            if (encryptedData == null) 
                throw new ArgumentNullException("encryptedData");
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows) 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 

            VerifyScope(scope); 

            // The RtlEncryptMemory and RtlDecryptMemory functions are available on WinXP and publicly published
            // in the ntsecapi.h header file as of Windows Server 2003.
            // The Rtl functions accept data in 8 byte increments, but we don't want applications to be able to make use of this, 
            // or else they're liable to break when the user upgrades.
            if ((encryptedData.Length == 0) || (encryptedData.Length % CAPI.CRYPTPROTECTMEMORY_BLOCK_SIZE != 0)) 
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_InvalidMemoryLength")); 

            uint dwFlags = (uint) scope; 
            try {
                // RtlDecryptMemory return an NTSTATUS
                int status = CAPI.SystemFunction041(encryptedData,
                                                    (uint) encryptedData.Length, 
                                                    dwFlags);
                if (status < 0) // non-negative numbers indicate success 
                    throw new CryptographicException(CAPI.CAPISafe.LsaNtStatusToWinError(status)); 
            }
            catch (EntryPointNotFoundException) { 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));
            }
        }
 
        private static void VerifyScope (MemoryProtectionScope scope) {
            if ((scope != MemoryProtectionScope.SameProcess) && (scope != MemoryProtectionScope.CrossProcess) && 
                (scope != MemoryProtectionScope.SameLogon)) 
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SecurityResources.GetResourceString("Arg_EnumIllegalVal"), (int) scope));
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
// [....]
// 
 
//
// DataProtection.cs 
//
// 01/25/2003
//
 
namespace System.Security.Cryptography
{ 
    using Microsoft.Win32; 
    using System.Runtime.CompilerServices;
    using System.Runtime.InteropServices; 
    using System.Runtime.ConstrainedExecution;
    using System.Security.Permissions;
    using System.Globalization;
 
    public enum DataProtectionScope {
        CurrentUser     = 0x00, 
        LocalMachine    = 0x01 
    }
 
    public enum MemoryProtectionScope {
        SameProcess     = 0x00,
        CrossProcess    = 0x01,
        SameLogon       = 0x02 
    }
 
    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] 
    public static class ProtectedData {
        [SecuritySafeCritical] 
        public static byte[] Protect (byte[] userData,
                                      byte[] optionalEntropy,
                                      DataProtectionScope scope) {
            if (userData == null) 
                throw new ArgumentNullException("userData");
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows) 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 

            GCHandle pbDataIn = new GCHandle(); 
            GCHandle pOptionalEntropy = new GCHandle();
            CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB();

            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                pbDataIn = GCHandle.Alloc(userData, GCHandleType.Pinned); 
                CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB(); 
                dataIn.cbData = (uint) userData.Length;
                dataIn.pbData = pbDataIn.AddrOfPinnedObject(); 
                CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB();
                if (optionalEntropy != null) {
                    pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);
                    entropy.cbData = (uint) optionalEntropy.Length; 
                    entropy.pbData = pOptionalEntropy.AddrOfPinnedObject();
                } 
                uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN; 
                if (scope == DataProtectionScope.LocalMachine)
                    dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE; 
                unsafe {
                    if (!CAPI.CryptProtectData(new IntPtr(&dataIn),
                                               String.Empty,
                                               new IntPtr(&entropy), 
                                               IntPtr.Zero,
                                               IntPtr.Zero, 
                                               dwFlags, 
                                               new IntPtr(&blob))) {
                        int lastWin32Error = Marshal.GetLastWin32Error(); 

                        // One of the most common reasons that DPAPI operations fail is that the user
                        // profile is not loaded (for instance in the case of impersonation or running in a
                        // service.  In those cases, throw an exception that provides more specific details 
                        // about what happened.
                        if (CAPI.ErrorMayBeCausedByUnloadedProfile(lastWin32Error)) { 
                            throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_ProfileMayNotBeLoaded")); 
                        }
                        else { 
                            throw new CryptographicException(lastWin32Error);
                        }
                    }
                } 

                // In some cases, the API would fail due to OOM but simply return a null pointer. 
                if (blob.pbData == IntPtr.Zero) 
                    throw new OutOfMemoryException();
 
                byte[] encryptedData = new byte[(int) blob.cbData];
                Marshal.Copy(blob.pbData, encryptedData, 0, encryptedData.Length);

                return encryptedData; 
            }
            catch (EntryPointNotFoundException) { 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 
            }
            finally { 
                if (pbDataIn.IsAllocated)
                   pbDataIn.Free();
                if (pOptionalEntropy.IsAllocated)
                   pOptionalEntropy.Free(); 
                if (blob.pbData != IntPtr.Zero) {
                    CAPI.CAPISafe.ZeroMemory(blob.pbData, blob.cbData); 
                    CAPI.CAPISafe.LocalFree(blob.pbData); 
                }
            } 
        }

        [SecuritySafeCritical]
        public static byte[] Unprotect (byte[] encryptedData, 
                                        byte[] optionalEntropy,
                                        DataProtectionScope scope) { 
            if (encryptedData == null) 
                throw new ArgumentNullException("encryptedData");
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows) 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));

            GCHandle pbDataIn = new GCHandle();
            GCHandle pOptionalEntropy = new GCHandle(); 
            CAPI.CRYPTOAPI_BLOB userData = new CAPI.CRYPTOAPI_BLOB();
 
            RuntimeHelpers.PrepareConstrainedRegions(); 
            try {
                pbDataIn = GCHandle.Alloc(encryptedData, GCHandleType.Pinned); 
                CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB();
                dataIn.cbData = (uint) encryptedData.Length;
                dataIn.pbData = pbDataIn.AddrOfPinnedObject();
                CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB(); 
                if (optionalEntropy != null) {
                    pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned); 
                    entropy.cbData = (uint) optionalEntropy.Length; 
                    entropy.pbData = pOptionalEntropy.AddrOfPinnedObject();
                } 
                uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN;
                if (scope == DataProtectionScope.LocalMachine)
                    dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE;
                unsafe { 
                    if (!CAPI.CryptUnprotectData(new IntPtr(&dataIn),
                                                 IntPtr.Zero, 
                                                 new IntPtr(&entropy), 
                                                 IntPtr.Zero,
                                                 IntPtr.Zero, 
                                                 dwFlags,
                                                 new IntPtr(&userData)))
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                } 

                // In some cases, the API would fail due to OOM but simply return a null pointer. 
                if (userData.pbData == IntPtr.Zero) 
                    throw new OutOfMemoryException();
 
                byte[] data = new byte[(int) userData.cbData];
                Marshal.Copy(userData.pbData, data, 0, data.Length);

                return data; 
            }
            catch (EntryPointNotFoundException) { 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 
            }
            finally { 
                if (pbDataIn.IsAllocated)
                   pbDataIn.Free();
                if (pOptionalEntropy.IsAllocated)
                   pOptionalEntropy.Free(); 
                if (userData.pbData != IntPtr.Zero) {
                    CAPI.CAPISafe.ZeroMemory(userData.pbData, userData.cbData); 
                    CAPI.CAPISafe.LocalFree(userData.pbData); 
                }
            } 
        }
    }

    [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] 
    public static class ProtectedMemory {
        [SecuritySafeCritical] 
        public static void Protect (byte[] userData, 
                                    MemoryProtectionScope scope) {
            if (userData == null) 
                throw new ArgumentNullException("userData");
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows)
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));
 
            VerifyScope(scope);
 
            // The RtlEncryptMemory and RtlDecryptMemory functions are available on WinXP and publicly published 
            // in the ntsecapi.h header file as of Windows Server 2003.
            // The Rtl functions accept data in 8 byte increments, but we don't want applications to be able to make use of this, 
            // or else they're liable to break when the user upgrades.
            if ((userData.Length == 0) || (userData.Length % CAPI.CRYPTPROTECTMEMORY_BLOCK_SIZE != 0))
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_InvalidMemoryLength"));
 
            uint dwFlags = (uint) scope;
            try { 
                // RtlEncryptMemory return an NTSTATUS 
                int status = CAPI.SystemFunction040(userData,
                                                    (uint) userData.Length, 
                                                    dwFlags);
                if (status < 0) // non-negative numbers indicate success
                    throw new CryptographicException(CAPI.CAPISafe.LsaNtStatusToWinError(status));
            } 
            catch (EntryPointNotFoundException) {
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 
            } 
        }
 
        [SecuritySafeCritical]
        public static void Unprotect (byte[] encryptedData,
                                      MemoryProtectionScope scope) {
            if (encryptedData == null) 
                throw new ArgumentNullException("encryptedData");
            if (Environment.OSVersion.Platform == PlatformID.Win32Windows) 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); 

            VerifyScope(scope); 

            // The RtlEncryptMemory and RtlDecryptMemory functions are available on WinXP and publicly published
            // in the ntsecapi.h header file as of Windows Server 2003.
            // The Rtl functions accept data in 8 byte increments, but we don't want applications to be able to make use of this, 
            // or else they're liable to break when the user upgrades.
            if ((encryptedData.Length == 0) || (encryptedData.Length % CAPI.CRYPTPROTECTMEMORY_BLOCK_SIZE != 0)) 
                throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_InvalidMemoryLength")); 

            uint dwFlags = (uint) scope; 
            try {
                // RtlDecryptMemory return an NTSTATUS
                int status = CAPI.SystemFunction041(encryptedData,
                                                    (uint) encryptedData.Length, 
                                                    dwFlags);
                if (status < 0) // non-negative numbers indicate success 
                    throw new CryptographicException(CAPI.CAPISafe.LsaNtStatusToWinError(status)); 
            }
            catch (EntryPointNotFoundException) { 
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT"));
            }
        }
 
        private static void VerifyScope (MemoryProtectionScope scope) {
            if ((scope != MemoryProtectionScope.SameProcess) && (scope != MemoryProtectionScope.CrossProcess) && 
                (scope != MemoryProtectionScope.SameLogon)) 
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, SecurityResources.GetResourceString("Arg_EnumIllegalVal"), (int) scope));
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK