예제 #1
0
        internal IntPtr ToUniStr(bool allocateFromHeap)
        {
            IntPtr ptr;

            EnsureNotDisposed();

            // Demand Permission
            new CryptographicPermission(CryptographicPermissionFlags.Decrypt).Demand();

            if (allocateFromHeap)
            {
                ptr = Marshal.AllocHGlobal((m_length + 1) * 2);
            }
            else
            {
                ptr = Marshal.AllocCoTaskMem((m_length + 1) * 2);
            }

            try
            {
                this.UnProtectMemory();
                Win32Native.ZeroMemory(ptr, (uint)((m_length + 1) * 2));
                Marshal.Copy(m_buffer, 0, ptr, m_length * 2);
                return(ptr);
            }
            finally
            {
                // Assert Permission
                new CryptographicPermission(CryptographicPermissionFlags.Encrypt).Assert();
                ProtectMemory();
            }
        }
예제 #2
0
 /// <summary>
 /// This will the allocated memory from method <see cref="SecureStringToGlobalAllocUni"/>.
 /// </summary>
 /// <remarks>
 /// This method is located in the <see cref="Marshal"/> class in .NET Framework v2.0
 /// </remarks>
 public static void ZeroFreeGlobalAllocUni(IntPtr s)
 {
     // Demand Permission
     new CryptographicPermission(CryptographicPermissionFlags.Decrypt).Demand();
     Win32Native.ZeroMemory(s, (uint)Win32Native.lstrlenW(s) * 2);
     Marshal.FreeHGlobal(s);
 }
예제 #3
0
        private void ClearBuffer()
        {
            // Clear the byte array
            Array.Clear(m_buffer, 0, m_buffer.Length);

            // Zero out the memory buffer
            Win32Native.ZeroMemory(m_bh.AddrOfPinnedObject(), (uint)m_buffer.Length);

            // Release the allocated memory
            if (m_bh.IsAllocated)
            {
                m_bh.Free();
            }
        }
예제 #4
0
        /// <summary>
        /// This method creates and displays a configurable dialog box that accepts credentials information from a user.
        /// </summary>
        /// <param name="targetName">Contains the name of the target for the credentials,
        /// typically a server name. For distributed file system (DFS) connections,
        /// this string is of the form "servername\sharename".
        /// This parameter is used to identify Target Information when storing and retrieving credentials.
        /// </param>
        /// <param name="caption">String containing the title for the dialog box.</param>
        /// <param name="message">String containing a brief message to display in the dialog box.</param>
        /// <param name="owner">Specifies the handle to the parent window of the dialog box.
        /// If this member is NULL, the desktop will be the parent window of the dialog box.
        /// </param>
        /// <returns><see cref="SecureCredential"/> object with the supplied credentials.</returns>
        /// <permission cref="UIPermission">Demand for <see cref="UIPermissionWindow.SafeTopLevelWindows"/> permission.</permission>
        public static SecureCredential PromptForSecureCredentials(string targetName, string caption, string message, IntPtr owner)
        {
            // Parameter validation
            if (targetName == null)
            {
                throw new ArgumentNullException("targetName");
            }
            if (caption == null)
            {
                caption = String.Empty;
            }
            if (message == null)
            {
                message = String.Empty;
            }

            new UIPermission(UIPermissionWindow.SafeTopLevelWindows).Demand();

            // Uncommment this lines to use custom bitmap
            // Bitmap credBMP = new Bitmap(@"..\credui.bmp");
            // replace IntPtr.Zero by credBMP.GetHbitmap()
            Win32Native.CREDUI_INFO creditUI = new Win32Native.CREDUI_INFO(owner, caption, message, IntPtr.Zero);
            int saveCredentials = 0;

            StringBuilder user = new StringBuilder(Win32Native.MAX_USER_NAME);

            byte[]   pwd       = new byte[Win32Native.MAX_PASSWORD];
            GCHandle pwdHandle = GCHandle.Alloc(pwd, GCHandleType.Pinned);

            try
            {
                Win32Native.CredUiFlags flags = Win32Native.CredUiFlags.GENERIC_CREDENTIALS |
                                                Win32Native.CredUiFlags.SHOW_SAVE_CHECK_BOX |
                                                Win32Native.CredUiFlags.ALWAYS_SHOW_UI |
                                                Win32Native.CredUiFlags.EXPECT_CONFIRMATION |
                                                Win32Native.CredUiFlags.INCORRECT_PASSWORD;

                //For more info see:
                //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/creduipromptforcredentials.asp
                //http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/dpapiusercredentials.asp?frame=true
                Win32Native.CredUIReturnCodes result = Win32Native.CredUIPromptForCredentialsW(
                    ref creditUI, targetName,
                    IntPtr.Zero, 0,
                    user, Win32Native.MAX_USER_NAME,
                    pwdHandle.AddrOfPinnedObject(), pwd.Length,
                    ref saveCredentials, flags);

                switch (result)
                {
                case Win32Native.CredUIReturnCodes.NO_ERROR:
                    StringBuilder usr    = new StringBuilder(Win32Native.MAX_USER_NAME);
                    StringBuilder domain = new StringBuilder(Win32Native.MAX_DOMAIN);
                    result = Win32Native.CredUIParseUserNameW(user.ToString(), usr, Win32Native.MAX_USER_NAME, domain, Win32Native.MAX_DOMAIN);
                    if (result == Win32Native.CredUIReturnCodes.NO_ERROR)
                    {
                        if (saveCredentials == 1)
                        {
                            ConfirmCredentials(targetName, true);
                        }
                        unsafe
                        {
                            return(new SecureCredential(usr.ToString(), (char *)pwdHandle.AddrOfPinnedObject().ToPointer(), Win32Native.lstrlenW(pwdHandle.AddrOfPinnedObject()), domain.ToString()));
                        }
                    }
                    else
                    {
                        throw new SecurityException(TranslateReturnCode(result));
                    }

                case Win32Native.CredUIReturnCodes.ERROR_CANCELLED:
                    return(null);

                default:
                    throw new SecurityException(TranslateReturnCode(result));
                }
            }
            finally
            {
                // Clear pwd data.
                Array.Clear(pwd, 0, pwd.Length);

                // Zero out the memory buffer
                Win32Native.ZeroMemory(pwdHandle.AddrOfPinnedObject(), (uint)pwd.Length);

                // Free the allocated handle
                if (pwdHandle.IsAllocated)
                {
                    pwdHandle.Free();
                }
            }
        }
예제 #5
0
        /// <summary>
        /// See <see cref="ProtectedData"/>.
        /// </summary>
        /// <param name="encryptedData">Data to unprotect.</param>
        /// <param name="optionalEntropy">Additional material to be added to the symmetric key used for encryption.</param>
        /// <param name="scope">See <see cref="DataProtectionScope"/>.</param>
        /// <returns>Plain text data.</returns>
        /// <exception cref="ArgumentNullException">The specified parameter is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="CryptographicException">Exception when executing unmanaged code.</exception>
        /// <permission cref="CryptographicPermission">Demand for decryption permission.</permission>
        public static byte[] Unprotect(byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope)
        {
            // Verify input
            if (encryptedData == null || encryptedData.Length == 0)
            {
                throw new ArgumentNullException("encryptedData");
            }
            if (!IsValidScope(scope))
            {
                throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.InvalidDataProtectionScope]);
            }

            // Demand Permission
            new CryptographicPermission(CryptographicPermissionFlags.Decrypt).Demand();
            // Assert UnamanagedCode (replaced by the SuppressUnmanagedCodeSecurity attribute of the Win32Native class

            // Initialize vars.
            // Check to see if the entropy is null
            if (optionalEntropy == null)
            {
                // Allocate something
                optionalEntropy = new byte[0];
            }

            Win32Native.CRYPTOAPI_BLOB plainTextBlob = new Win32Native.CRYPTOAPI_BLOB();

            GCHandle encryptedDataHandle = GCHandle.Alloc(encryptedData, GCHandleType.Pinned);
            GCHandle entropyHandle       = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);

            try
            {
                Win32Native.CRYPTPROTECT_PROMPTSTRUCT prompt = new Win32Native.CRYPTPROTECT_PROMPTSTRUCT(0);

                Win32Native.CRYPTOAPI_BLOB encryptedDataBlob = new Win32Native.CRYPTOAPI_BLOB();
                encryptedDataBlob.cbData = (uint)encryptedData.Length;
                encryptedDataBlob.pbData = encryptedDataHandle.AddrOfPinnedObject();

                Win32Native.CRYPTOAPI_BLOB entropyBlob = new Win32Native.CRYPTOAPI_BLOB();
                entropyBlob.cbData = (uint)optionalEntropy.Length;
                entropyBlob.pbData = entropyHandle.AddrOfPinnedObject();

                if (!Win32Native.CryptUnprotectData(ref encryptedDataBlob,
                                                    null,
                                                    ref entropyBlob,
                                                    IntPtr.Zero,
                                                    ref prompt,
                                                    (uint)scope,
                                                    ref plainTextBlob))
                {
                    throw new CryptographicException(Resource.ResourceManager[Resource.MessageKey.UnprotectDataException], new Win32Exception(Marshal.GetLastWin32Error()));
                }

                if (plainTextBlob.pbData == IntPtr.Zero)
                {
                    throw new OutOfMemoryException(Resource.ResourceManager[Resource.MessageKey.OutOfMemoryException, "plainTextBlob"]);
                }

                byte[] plainText = new byte[plainTextBlob.cbData];
                Marshal.Copy(plainTextBlob.pbData, plainText, 0, plainText.Length);

                return(plainText);
            }
            finally
            {
                // Free handles
                if (encryptedDataHandle.IsAllocated)
                {
                    encryptedDataHandle.Free();
                }
                if (entropyHandle.IsAllocated)
                {
                    entropyHandle.Free();
                }
                //Free the unmanaged resource ...
                // Free and erase the plainTextBlob
                if (plainTextBlob.pbData != IntPtr.Zero)
                {
                    Win32Native.ZeroMemory(plainTextBlob.pbData, plainTextBlob.cbData);
                    Win32Native.LocalFree(plainTextBlob.pbData);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// This function performs encryption on the data in a byte array input data.
        /// If <see cref="DataProtectionScope.CurrentUser"/> is specified, only a user
        /// with the same logon credentials as the encrypter can decrypt the data.
        /// <b>Warning</b>If the logon credentials are lost or forgotten, the data is usually unrecoverable.
        /// If the <see cref="DataProtectionScope.LocalMachine"/> is used, the encryption and decryption must be done on the same computer
        /// therefore any user on the same computer where the data was encrypted can recover the data.
        /// </summary>
        /// <remarks>
        /// The function creates a session key to perform the encryption.
        /// The session key is rederived when the data is to be decrypted.
        /// The function also adds a message authentication code (MAC), which is a keyed integrity check, to the encrypted data to guard against data tampering.
        /// </remarks>
        /// <param name="userData">Data to be protected. This array should be erased after use with <see cref="Array.Clear"/>.</param>
        /// <param name="optionalEntropy">Additional material to be added to the symmetric key used for encryption.</param>
        /// <param name="scope">See <see cref="DataProtectionScope"/>.</param>
        /// <returns>Protected data.</returns>
        /// <exception cref="ArgumentNullException">The specified parameter is a null reference (Nothing in Visual Basic).</exception>
        /// <exception cref="CryptographicException">Exception when executing unmanaged code.</exception>
        /// <permission cref="CryptographicPermission">Demand for encryption permission.</permission>
        public static byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope)
        {
            // Verify input
            if (userData == null)
            {
                throw new ArgumentNullException("userData");
            }
            if (!IsValidScope(scope))
            {
                throw new ArgumentException(Resource.ResourceManager[Resource.MessageKey.InvalidDataProtectionScope]);
            }

            // Demand Permission
            new CryptographicPermission(CryptographicPermissionFlags.Encrypt).Demand();
            // Assert UnamanagedCode (replaced by the SuppressUnmanagedCodeSecurity attribute of the Win32Native class

            // Check to see if the entropy is null
            if (optionalEntropy == null)
            {
                // Allocate something
                optionalEntropy = new byte[0];
            }

            Win32Native.CRYPTOAPI_BLOB cipherTextBlob = new Win32Native.CRYPTOAPI_BLOB();

            // This prevents the garbage collector from moving the object and hence
            // undermines the efficiency of the garbage collector. We 'll release
            // the reference on the finally block.
            GCHandle userDataHandle = GCHandle.Alloc(userData, GCHandleType.Pinned);
            GCHandle entropyHandle  = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned);

            try
            {
                Win32Native.CRYPTPROTECT_PROMPTSTRUCT prompt = new Win32Native.CRYPTPROTECT_PROMPTSTRUCT(0);

                Win32Native.CRYPTOAPI_BLOB plainTextBlob = new Win32Native.CRYPTOAPI_BLOB();
                plainTextBlob.cbData = (uint)userData.Length;
                plainTextBlob.pbData = userDataHandle.AddrOfPinnedObject();

                Win32Native.CRYPTOAPI_BLOB entropyBlob = new Win32Native.CRYPTOAPI_BLOB();
                entropyBlob.cbData = (uint)optionalEntropy.Length;
                entropyBlob.pbData = entropyHandle.AddrOfPinnedObject();

                if (!Win32Native.CryptProtectData(ref plainTextBlob,
                                                  null,
                                                  ref entropyBlob,
                                                  IntPtr.Zero,
                                                  ref prompt,
                                                  (uint)scope,
                                                  ref cipherTextBlob))
                {
                    throw new CryptographicException(Resource.ResourceManager[Resource.MessageKey.ProtectDataException], new Win32Exception(Marshal.GetLastWin32Error()));
                }

                //Check returned data
                if (cipherTextBlob.pbData == IntPtr.Zero)
                {
                    throw new OutOfMemoryException(Resource.ResourceManager[Resource.MessageKey.OutOfMemoryException, "cipherTextBlob"]);
                }

                // Move encrypted data to the returned array
                byte[] cipherText = new byte[cipherTextBlob.cbData];
                Marshal.Copy(cipherTextBlob.pbData, cipherText, 0, cipherText.Length);

                return(cipherText);
            }
            finally
            {
                // Free the allocated handles
                if (userDataHandle.IsAllocated)
                {
                    userDataHandle.Free();
                }
                if (entropyHandle.IsAllocated)
                {
                    entropyHandle.Free();
                }
                //Free the unmanaged resource ...
                // Free and erase the cipherTextBlob
                if (cipherTextBlob.pbData != IntPtr.Zero)
                {
                    Win32Native.ZeroMemory(cipherTextBlob.pbData, cipherTextBlob.cbData);
                    Win32Native.LocalFree(cipherTextBlob.pbData);
                }
            }
        }