SafeCryptoKeyHandle.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / infocard / Service / managed / Microsoft / InfoCards / SafeCryptoKeyHandle.cs / 1 / SafeCryptoKeyHandle.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace Microsoft.InfoCards 
{
    using System; 
    using System.ComponentModel; 
    using System.Globalization;
    using System.Runtime.InteropServices; 
    using System.Runtime.ConstrainedExecution;
    using System.Security.Cryptography;
    using System.Security;
    using Microsoft.InfoCards.Diagnostics; 
    using IDT=Microsoft.InfoCards.Diagnostics.InfoCardTrace;
 
 

    internal class SafeCryptoKey : IDisposable 
    {
        //
        // The plaintextkeyblob structure used to hold the keying information
        // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/seccrypto/security/publickeystruc.asp 
        // for details of the structure
        // 
        [StructLayout(LayoutKind.Explicit, Size=12, CharSet=CharSet.Ansi)] 
        struct BlobHeader
        { 
            const int PLAINTEXTKEYBLOB = 0x08;
            const int CUR_BLOB_VERSION = 0x02;
            const int CALG_AES =0x00006610;
            [FieldOffset(0)] public byte bType; 
            [FieldOffset(1)] public byte bVersion;
            [FieldOffset(2)] public UInt16 reserved; 
            [FieldOffset(4)] public UInt32   aiKeyAlg; 
            [FieldOffset(8)] public UInt32 keyLength;
            public BlobHeader( int keySize ) 
            {
                bType = PLAINTEXTKEYBLOB;
                bVersion = CUR_BLOB_VERSION;
                reserved = 0; 
                aiKeyAlg = CALG_AES;
                keyLength = (uint)keySize; 
            } 
        }
 
        [DllImport( "advapi32.dll",
                EntryPoint      ="CryptSetKeyParam",
                CharSet         = CharSet.Unicode,
                ExactSpelling   = true, 
                SetLastError    = true ) ]
        [SuppressUnmanagedCodeSecurity] 
        private static extern bool CryptSetKeyParam( 
              [In] SafeCryptoKeyHandle hKey,
              [In] UInt32 dwParam, 
              [In] IntPtr data,
              [In] UInt32 flags);

         [DllImport( "advapi32.dll", 
               EntryPoint      ="CryptImportKey",
               CharSet         = CharSet.Unicode, 
               ExactSpelling   = true, 
               SetLastError    = true ) ]
        [SuppressUnmanagedCodeSecurity] 
        private static extern bool CryptImportKey(
                     [In] SafeRsaProviderHandle hProv,
                     [In] IntPtr pbKeyData,
                     [In] UInt32 dwDataLen, 
                     [In] IntPtr hPubKey,
                     [In] UInt32 dwFlags, 
                     [Out] out SafeCryptoKeyHandle hKey ); 

        private SafeCryptoKeyHandle m_handle; 

        public SafeCryptoKeyHandle Handle
        {
            get 
            {
                return m_handle; 
            } 
        }
        unsafe public SafeCryptoKey( SafeRsaProviderHandle provider, byte[] encryptedKey, byte[] iv ) 
        {
            //
            // These constants from wincrypt.h
            // 
            const int   KP_IV = 1;
            const int HEADER_SIZE = 12; 
 

 
            IDT.DebugAssert( 32 == encryptedKey.Length , "unexpected key length" );
            IDT.DebugAssert( null != provider, "null provider" );

            // 
            // The key needs to be prefixed with a standard preamble to make it into a plaintext key blob.
            // 
            BlobHeader bh = new BlobHeader( encryptedKey.Length ); 
            IDT.DebugAssert( 12 == sizeof( BlobHeader ) , "size of blob header must be 12 bytes" );
 
            int bufferSize = sizeof( BlobHeader ) + encryptedKey.Length;
            byte*  keyBuffer = stackalloc byte[ bufferSize ];

            // 
            // Copy the blob header over the first 12 bytes of the keyBuffer
            // 
            byte* pbh = (byte *)&bh; 
            for( int i = 0; i < HEADER_SIZE; i++ )
            { 
               keyBuffer[i] = pbh[i];
            }

 
            try
            { 
                ProtectedMemory.Unprotect( encryptedKey, MemoryProtectionScope.SameProcess ); 
                for( int i = 0; i < encryptedKey.Length; i++ )
                { 
                    keyBuffer[ HEADER_SIZE + i ] = encryptedKey[ i ];
                }
            }
            finally 
            {
               ProtectedMemory.Protect( encryptedKey, MemoryProtectionScope.SameProcess ); 
            } 

            if( !CryptImportKey( 
                   provider,
                   (IntPtr)keyBuffer,
                   (uint)bufferSize,
                   IntPtr.Zero, 
                   0x00,
                   out m_handle ) ) 
            { 
                Exception e = new Win32Exception( Marshal.GetLastWin32Error() );
                IDT.CloseInvalidOutSafeHandle(m_handle); 
                IDT.TraceAndLogException( e );
                throw IDT.ThrowHelperError( e );
            }
 
            //
            // Setup the iv. 
            // 
            fixed( byte * piv = &iv[0] )
            { 
               if( !CryptSetKeyParam(
                   m_handle,
                   KP_IV,
                   (IntPtr) piv, 
                   0 ) )
               { 
                   int error = Marshal.GetLastWin32Error(); 
                   Exception e = new Win32Exception( error );
                   m_handle.Dispose(); 
                   throw IDT.ThrowHelperError( e );
               }
            }
        } 
        void IDisposable.Dispose()
        { 
            m_handle.Dispose(); 
        }
 

    }

    // 
    // Summary:
    // Provides a wrapper over a handle retrieved by CryptImportKey 
    // 
    internal class SafeCryptoKeyHandle : SafeHandle
    { 


        [DllImport( "advapi32.dll",
                    EntryPoint      ="CryptDestroyKey", 
                    CharSet         = CharSet.Unicode,
                    ExactSpelling   = true, 
                    SetLastError    = true ) ] 
       [SuppressUnmanagedCodeSecurity]
       [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 
       private static extern bool CryptDestroyKey( [In] IntPtr hKey );


 

        private SafeCryptoKeyHandle() : base( IntPtr.Zero, true ) 
        { 
        }
 

        public override bool IsInvalid
        {
            get 
            {
                return ( IntPtr.Zero == base.handle ); 
            } 
        }
 

        protected override bool ReleaseHandle()
        {
            #pragma warning suppress 56523 
            return CryptDestroyKey( base.handle );
 
        } 

    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

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