BCryptNative.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Core / System / Security / Cryptography / BCryptNative.cs / 1305376 / BCryptNative.cs

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

using System; 
using System.Diagnostics; 
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices; 
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Diagnostics.Contracts;
using Microsoft.Win32; 
using Microsoft.Win32.SafeHandles;
 
namespace System.Security.Cryptography { 
    /// 
    ///     Native interop with CNG's BCrypt layer. Native definitions can be found in bcrypt.h 
    /// 
    internal static class BCryptNative {
        /// 
        ///     Well known algorithm names 
        /// 
        internal static class AlgorithmName { 
            public const string ECDHP256 = "ECDH_P256";         // BCRYPT_ECDH_P256_ALGORITHM 
            public const string ECDHP384 = "ECDH_P384";         // BCRYPT_ECDH_P384_ALGORITHM
            public const string ECDHP521 = "ECDH_P521";         // BCRYPT_ECDH_P521_ALGORITHM 
            public const string ECDsaP256 = "ECDSA_P256";       // BCRYPT_ECDSA_P256_ALGORITHM
            public const string ECDsaP384 = "ECDSA_P384";       // BCRYPT_ECDSA_P384_ALGORITHM
            public const string ECDsaP521 = "ECDSA_P521";       // BCRYPT_ECDSA_P521_ALGORITHM
            public const string MD5 = "MD5";                    // BCRYPT_MD5_ALGORITHM 
            public const string Sha1 = "SHA1";                  // BCRYPT_SHA1_ALGORITHM
            public const string Sha256 = "SHA256";              // BCRYPT_SHA256_ALGORITHM 
            public const string Sha384 = "SHA384";              // BCRYPT_SHA384_ALGORITHM 
            public const string Sha512 = "SHA512";              // BCRYPT_SHA512_ALGORITHM
        } 

        /// 
        ///     Result codes from BCrypt APIs
        ///  
        internal enum ErrorCode {
            Success = 0x00000000,                               // STATUS_SUCCESS 
            BufferToSmall = unchecked((int)0xC0000023),         // STATUS_BUFFER_TOO_SMALL 
            ObjectNameNotFound = unchecked((int)0xC0000034)     // SATUS_OBJECT_NAME_NOT_FOUND
        } 

        /// 
        ///     Well known BCrypt hash property names
        ///  
        internal static class HashPropertyName {
            public const string HashLength = "HashDigestLength";        // BCRYPT_HASH_LENGTH 
        } 

        ///  
        ///     Magic numbers identifying blob types
        /// 
        internal enum KeyBlobMagicNumber {
            ECDHPublicP256 = 0x314B4345,                        // BCRYPT_ECDH_PUBLIC_P256_MAGIC 
            ECDHPublicP384 = 0x334B4345,                        // BCRYPT_ECDH_PUBLIC_P384_MAGIC
            ECDHPublicP521 = 0x354B4345,                        // BCRYPT_ECDH_PUBLIC_P521_MAGIC 
            ECDsaPublicP256 = 0x31534345,                       // BCRYPT_ECDSA_PUBLIC_P256_MAGIC 
            ECDsaPublicP384 = 0x33534345,                       // BCRYPT_ECDSA_PUBLIC_P384_MAGIC
            ECDsaPublicP521 = 0x35534345                        // BCRYPT_ECDSA_PUBLIC_P521_MAGIC 
        }

        /// 
        ///     Well known KDF names 
        /// 
        internal static class KeyDerivationFunction { 
            public const string Hash = "HASH";                  // BCRYPT_KDF_HASH 
            public const string Hmac = "HMAC";                  // BCRYPT_KDF_HMAC
            public const string Tls = "TLS_PRF";                // BCRYPT_KDF_TLS_PRF 
        }

        /// 
        ///     Well known BCrypt provider names 
        /// 
        internal static class ProviderName { 
            public const string MicrosoftPrimitiveProvider = "Microsoft Primitive Provider";    // MS_PRIMITIVE_PROVIDER 
        }
 
        /// 
        ///     Well known BCrypt object property names
        /// 
        internal static class ObjectPropertyName { 
            public const string ObjectLength = "ObjectLength";          // BCRYPT_OBJECT_LENGTH
        } 
 
#pragma warning disable 618    // Have not migrated to v4 transparency yet
        [SecurityCritical(SecurityCriticalScope.Everything)] 
#pragma warning restore 618
        [SuppressUnmanagedCodeSecurity]
        internal static class UnsafeNativeMethods {
            ///  
            ///     Create a hash object
            ///  
            [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)] 
            internal static extern ErrorCode BCryptCreateHash(SafeBCryptAlgorithmHandle hAlgorithm,
                                                              [Out] out SafeBCryptHashHandle phHash, 
                                                              IntPtr pbHashObject,
                                                              int cbHashObject,
                                                              IntPtr pbSecret,
                                                              int cbSecret, 
                                                              int dwFlags);
 
            ///  
            ///     Get a property from a BCrypt algorithm object
            ///  
            [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
            internal static extern ErrorCode BCryptGetProperty(SafeBCryptAlgorithmHandle hObject,
                                                               string pszProperty,
                                                               [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput, 
                                                               int cbOutput,
                                                               [In, Out] ref int pcbResult, 
                                                               int flags); 

            ///  
            ///     Get a property from a BCrypt algorithm object
            /// 
            [DllImport("bcrypt.dll", EntryPoint = "BCryptGetProperty", CharSet = CharSet.Unicode)]
            internal static extern ErrorCode BCryptGetAlgorithmProperty(SafeBCryptAlgorithmHandle hObject, 
                                                                        string pszProperty,
                                                                        [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput, 
                                                                        int cbOutput, 
                                                                        [In, Out] ref int pcbResult,
                                                                        int flags); 

            /// 
            ///     Get a property from a BCrypt hash object
            ///  
            [DllImport("bcrypt.dll", EntryPoint = "BCryptGetProperty", CharSet = CharSet.Unicode)]
            internal static extern ErrorCode BCryptGetHashProperty(SafeBCryptHashHandle hObject, 
                                                                   string pszProperty, 
                                                                   [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
                                                                   int cbOutput, 
                                                                   [In, Out] ref int pcbResult,
                                                                   int flags);

            ///  
            ///     Get the hash value of the data
            ///  
            [DllImport("bcrypt.dll")] 
            internal static extern ErrorCode BCryptFinishHash(SafeBCryptHashHandle hHash,
                                                              [MarshalAs(UnmanagedType.LPArray), Out] byte[] pbInput, 
                                                              int cbInput,
                                                              int dwFlags);

            ///  
            ///     Hash a block of data
            ///  
            [DllImport("bcrypt.dll")] 
            internal static extern ErrorCode BCryptHashData(SafeBCryptHashHandle hHash,
                                                            [MarshalAs(UnmanagedType.LPArray), In] byte[] pbInput, 
                                                            int cbInput,
                                                            int dwFlags);

            ///  
            ///     Get a handle to an algorithm provider
            ///  
            [DllImport("bcrypt.dll", CharSet = CharSet.Unicode)] 
            internal static extern ErrorCode BCryptOpenAlgorithmProvider([Out] out SafeBCryptAlgorithmHandle phAlgorithm,
                                                                         string pszAlgId,             // BCryptAlgorithm 
                                                                         string pszImplementation,    // ProviderNames
                                                                         int dwFlags);
        }
 
        //
        // Wrapper and utility functions 
        // 

        ///  
        ///     Adapter to wrap specific BCryptGetProperty P/Invokes with a generic handle type
        /// 
        private delegate ErrorCode BCryptPropertyGetter(T hObject,
                                                           string pszProperty, 
                                                           byte[] pbOutput,
                                                           int cbOutput, 
                                                           ref int pcbResult, 
                                                           int dwFlags) where T : SafeHandle;
 
        private static bool? s_bcryptSupported;

        /// 
        ///     Determine if BCrypt is supported on the current machine 
        /// 
        internal static bool BCryptSupported { 
            //  
            // 
            //  
            // 
            // 
            [System.Security.SecurityCritical]
            [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Reviewed")] 
            get {
                if (!s_bcryptSupported.HasValue) { 
                    // Attempt to load bcrypt.dll to see if the BCrypt CNG APIs are available on the machine 
                    using (SafeLibraryHandle bcrypt = Microsoft.Win32.UnsafeNativeMethods.LoadLibraryEx("bcrypt", IntPtr.Zero, 0)) {
                        s_bcryptSupported = !bcrypt.IsInvalid; 
                    }
                }

                return s_bcryptSupported.Value; 
            }
        } 
 
        /// 
        ///     Get the value of a DWORD property of a BCrypt object 
        /// 
        // 
        // 
        //  
        [System.Security.SecurityCritical]
        internal static int GetInt32Property(T algorithm, string property) where T : SafeHandle { 
            Contract.Requires(algorithm != null); 
            Contract.Requires(property == HashPropertyName.HashLength ||
                              property == ObjectPropertyName.ObjectLength); 

            return BitConverter.ToInt32(GetProperty(algorithm, property), 0);
        }
 
        /// 
        ///     Get the value of a property of a BCrypt object 
        ///  
        // 
        //  
        // 
        // 
        [System.Security.SecurityCritical]
        internal static byte[] GetProperty(T algorithm, string property) where T : SafeHandle { 
            Contract.Requires(algorithm != null);
            Contract.Requires(!String.IsNullOrEmpty(property)); 
            Contract.Ensures(Contract.Result() != null); 

            BCryptPropertyGetter getter = null; 
            if (typeof(T) == typeof(SafeBCryptAlgorithmHandle)) {
                getter = new BCryptPropertyGetter(UnsafeNativeMethods.BCryptGetAlgorithmProperty)
                    as BCryptPropertyGetter;
            } 
            else if (typeof(T) == typeof(SafeBCryptHashHandle)) {
                getter = new BCryptPropertyGetter(UnsafeNativeMethods.BCryptGetHashProperty) 
                    as BCryptPropertyGetter; 
            }
 
            Debug.Assert(getter != null, "Unknown handle type");

            // Figure out how big the property is
            int bufferSize = 0; 
            ErrorCode error = getter(algorithm, property, null, 0, ref bufferSize, 0);
 
            if (error != ErrorCode.BufferToSmall && error != ErrorCode.Success) { 
                throw new CryptographicException((int)error);
            } 

            // Allocate the buffer, and return the property
            Debug.Assert(bufferSize > 0, "bufferSize > 0");
            byte[] buffer = new byte[bufferSize]; 
            error = getter(algorithm, property, buffer, buffer.Length, ref bufferSize, 0);
 
            if (error != ErrorCode.Success) { 
                throw new CryptographicException((int)error);
            } 

            return buffer;
        }
 

        ///  
        ///     Map an algorithm identifier to a key size and magic number 
        /// 
        internal static void MapAlgorithmIdToMagic(string algorithm, 
                                                   out KeyBlobMagicNumber algorithmMagic,
                                                   out int keySize) {
            Contract.Requires(!String.IsNullOrEmpty(algorithm));
 
            switch (algorithm) {
                case AlgorithmName.ECDHP256: 
                    algorithmMagic = KeyBlobMagicNumber.ECDHPublicP256; 
                    keySize = 256;
                    break; 

                case AlgorithmName.ECDHP384:
                    algorithmMagic = KeyBlobMagicNumber.ECDHPublicP384;
                    keySize = 384; 
                    break;
 
                case AlgorithmName.ECDHP521: 
                    algorithmMagic = KeyBlobMagicNumber.ECDHPublicP521;
                    keySize = 521; 
                    break;

                case AlgorithmName.ECDsaP256:
                    algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP256; 
                    keySize = 256;
                    break; 
 
                case AlgorithmName.ECDsaP384:
                    algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP384; 
                    keySize = 384;
                    break;

                case AlgorithmName.ECDsaP521: 
                    algorithmMagic = KeyBlobMagicNumber.ECDsaPublicP521;
                    keySize = 521; 
                    break; 

                default: 
                    throw new ArgumentException(SR.GetString(SR.Cryptography_UnknownEllipticCurveAlgorithm));
            }
        }
 
        /// 
        ///     Open a handle to an algorithm provider 
        ///  
        // 
        //  
        // 
        // 
        // 
        //  
        // 
        [System.Security.SecurityCritical] 
        internal static SafeBCryptAlgorithmHandle OpenAlgorithm(string algorithm, string implementation) { 
            Contract.Requires(!String.IsNullOrEmpty(algorithm));
            Contract.Requires(!String.IsNullOrEmpty(implementation)); 
            Contract.Ensures(Contract.Result() != null &&
                             !Contract.Result().IsInvalid &&
                             !Contract.Result().IsClosed);
 
            SafeBCryptAlgorithmHandle algorithmHandle = null;
            ErrorCode error = UnsafeNativeMethods.BCryptOpenAlgorithmProvider(out algorithmHandle, 
                                                                              algorithm, 
                                                                              implementation,
                                                                              0); 

            if (error != ErrorCode.Success) {
                throw new CryptographicException((int)error);
            } 

            return algorithmHandle; 
        } 
    }
} 

// 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