コード例 #1
0
        internal static Microsoft.Win32.SafeHandles.SafeCspHandle AcquireCsp(string keyContainer,
                                                                             string providerName,
                                                                             ProviderType providerType,
                                                                             CryptAcquireContextFlags flags,
                                                                             bool throwPlatformException)
        {
            Contract.Ensures(Contract.Result <SafeCspHandle>() != null &&
                             !Contract.Result <SafeCspHandle>().IsInvalid&&
                             !Contract.Result <SafeCspHandle>().IsClosed);

            Microsoft.Win32.SafeHandles.SafeCspHandle cspHandle = null;
            if (!UnsafeNativeMethods.CryptAcquireContext(out cspHandle,
                                                         keyContainer,
                                                         providerName,
                                                         providerType,
                                                         flags))
            {
                // If the platform doesn't have the specified CSP, we'll either get a ProviderTypeNotDefined
                // or a KeysetNotDefined error depending on the CAPI version.
                int error = Marshal.GetLastWin32Error();

                if (throwPlatformException && (error == (int)CapiNative.ErrorCode.ProviderTypeNotDefined ||
                                               error == (int)CapiNative.ErrorCode.KeysetNotDefined))
                {
                    throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported));
                }
                else
                {
                    throw new CryptographicException(error);
                }
            }

            return(cspHandle);
        }
コード例 #2
0
        public AesCryptoServiceProvider () {
            Contract.Ensures(m_cspHandle != null && !m_cspHandle.IsInvalid && !m_cspHandle.IsClosed);

            // On Windows XP the AES CSP has the prototype name, but on newer operating systems it has the
            // standard name
            string providerName = CapiNative.ProviderNames.MicrosoftEnhancedRsaAes;
            if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1) {
                providerName = CapiNative.ProviderNames.MicrosoftEnhancedRsaAesPrototype;
            }

            m_cspHandle = CapiNative.AcquireCsp(null,
                                                providerName,
                                                CapiNative.ProviderType.RsaAes,
                                                CapiNative.CryptAcquireContextFlags.VerifyContext,
                                                true);

            // CAPI will not allow feedback sizes greater than 64 bits
            FeedbackSizeValue = 8;

            // Get the different AES key sizes supported by this platform, raising an error if there are no
            // supported key sizes.
            int defaultKeySize = 0;
            KeySizes[] keySizes = FindSupportedKeySizes(m_cspHandle, out defaultKeySize);
            if (keySizes.Length != 0) {
                Debug.Assert(defaultKeySize > 0, "defaultKeySize > 0");
                KeySizeValue = defaultKeySize;
            }
            else {
                throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported));
            }
        }
コード例 #3
0
        public SafeCspHandle Duplicate()
        {
            Contract.Requires(!IsInvalid && !IsClosed);

            // In the window between the call to CryptContextAddRef and when the raw handle value is assigned
            // into this safe handle, there's a second reference to the original safe handle that the CLR does
            // not know about, so we need to bump the reference count around this entire operation to ensure
            // that we don't have the original handle closed underneath us.
            bool acquired = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                DangerousAddRef(ref acquired);
                IntPtr originalHandle = DangerousGetHandle();

                int error = (int)CapiNative.ErrorCode.Success;

                SafeCspHandle duplicate = new SafeCspHandle();

                // A successful call to CryptContextAddRef and an assignment of the handle value to the duplicate
                // SafeHandle need to happen atomically, so we contain them within a CER.
                RuntimeHelpers.PrepareConstrainedRegions();
                try { }
                finally
                {
                    if (!CryptContextAddRef(this, IntPtr.Zero, 0))
                    {
                        error = Marshal.GetLastWin32Error();
                    }
                    else
                    {
                        duplicate.SetHandle(originalHandle);
                    }
                }

                // If we could not call CryptContextAddRef succesfully, then throw the error here otherwise
                // we should be in a valid state at this point.
                if (error != (int)CapiNative.ErrorCode.Success)
                {
                    duplicate.Dispose();
                    throw new CryptographicException(error);
                }
                else
                {
                    Debug.Assert(!duplicate.IsInvalid, "Failed to duplicate handle successfully");
                }

                return(duplicate);
            }
            finally
            {
                if (acquired)
                {
                    DangerousRelease();
                }
            }
        }
コード例 #4
0
        internal static T GetProviderParameterStruct <T>(Microsoft.Win32.SafeHandles.SafeCspHandle provider,
                                                         ProviderParameter parameter,
                                                         ProviderParameterFlags flags) where T : struct
        {
            Contract.Requires(provider != null);
            Contract.Requires(parameter == ProviderParameter.EnumerateAlgorithms);

            // Figure out how big the parameter is
            int    bufferSize = 0;
            IntPtr buffer     = IntPtr.Zero;

            if (!UnsafeNativeMethods.CryptGetProvParam(provider, parameter, buffer, ref bufferSize, flags))
            {
                int errorCode = Marshal.GetLastWin32Error();

                // NoMoreItems means that we've finished the enumeration we're currently working on, this is
                // not a real error, so return an empty structure to mark the end.
                if (errorCode == (int)ErrorCode.NoMoreItems)
                {
                    return(new T());
                }
                else if (errorCode != (int)ErrorCode.MoreData)
                {
                    throw new CryptographicException(errorCode);
                }
            }

            Debug.Assert(Marshal.SizeOf(typeof(T)) <= bufferSize, "Buffer size does not match structure size");

            //
            // Pull the parameter back and marshal it into the return structure
            //

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                // Allocate in a CER because we could fail between the alloc and the assignment
                RuntimeHelpers.PrepareConstrainedRegions();
                try { }
                finally {
                    buffer = Marshal.AllocCoTaskMem(bufferSize);
                }

                if (!UnsafeNativeMethods.CryptGetProvParam(provider, parameter, buffer, ref bufferSize, flags))
                {
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }

                return((T)Marshal.PtrToStructure(buffer, typeof(T)));
            }
            finally {
                if (buffer != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(buffer);
                }
            }
        }
コード例 #5
0
        // SafeCritical - we're not exposing out anything that we want to prevent untrusted code from getting at
        public CapiHashAlgorithm(string provider,
                                 CapiNative.ProviderType providerType,
                                 CapiNative.AlgorithmId algorithm) {
            Contract.Requires(!String.IsNullOrEmpty(provider));
            Contract.Requires((CapiNative.AlgorithmClass)((uint)algorithm & (uint)CapiNative.AlgorithmClass.Hash) == CapiNative.AlgorithmClass.Hash);
            Contract.Ensures(m_cspHandle != null && !m_cspHandle.IsInvalid && !m_cspHandle.IsClosed);
            Contract.Ensures(m_hashHandle != null && !m_hashHandle.IsInvalid && !m_hashHandle.IsClosed);

            m_algorithmId = algorithm;
            m_cspHandle = CapiNative.AcquireCsp(null,
                                                provider,
                                                providerType,
                                                CapiNative.CryptAcquireContextFlags.VerifyContext,
                                                true);
            Initialize();
        }
コード例 #6
0
        // SafeCritical - we're not exposing out anything that we want to prevent untrusted code from getting at
        public CapiHashAlgorithm(string provider,
                                 CapiNative.ProviderType providerType,
                                 CapiNative.AlgorithmId algorithm)
        {
            Contract.Requires(!String.IsNullOrEmpty(provider));
            Contract.Requires((CapiNative.AlgorithmClass)((uint)algorithm & (uint)CapiNative.AlgorithmClass.Hash) == CapiNative.AlgorithmClass.Hash);
            Contract.Ensures(m_cspHandle != null && !m_cspHandle.IsInvalid && !m_cspHandle.IsClosed);
            Contract.Ensures(m_hashHandle != null && !m_hashHandle.IsInvalid && !m_hashHandle.IsClosed);

            m_algorithmId = algorithm;
            m_cspHandle   = CapiNative.AcquireCsp(null,
                                                  provider,
                                                  providerType,
                                                  CapiNative.CryptAcquireContextFlags.VerifyContext,
                                                  true);
            Initialize();
        }
コード例 #7
0
        internal void SetParentCsp(SafeCspHandle parentCsp)
        {
            bool addedRef = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                parentCsp.DangerousAddRef(ref addedRef);
                IntPtr rawParentHandle = parentCsp.DangerousGetHandle();
                ParentCsp = rawParentHandle;
            }
            finally {
                if (addedRef)
                {
                    parentCsp.DangerousRelease();
                }
            }
        }
コード例 #8
0
 public SafeCspHandle Duplicate()
 {
     SafeCspHandle handle2;
     bool success = false;
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         base.DangerousAddRef(ref success);
         IntPtr ptr = base.DangerousGetHandle();
         int hr = 0;
         SafeCspHandle handle = new SafeCspHandle();
         RuntimeHelpers.PrepareConstrainedRegions();
         try
         {
         }
         finally
         {
             if (!CryptContextAddRef(this, IntPtr.Zero, 0))
             {
                 hr = Marshal.GetLastWin32Error();
             }
             else
             {
                 handle.SetHandle(ptr);
             }
         }
         if (hr != 0)
         {
             handle.Dispose();
             throw new CryptographicException(hr);
         }
         handle2 = handle;
     }
     finally
     {
         if (success)
         {
             base.DangerousRelease();
         }
     }
     return handle2;
 }
コード例 #9
0
 public CapiSymmetricAlgorithm(int blockSize,
                               int feedbackSize,
                               Microsoft.Win32.SafeHandles.SafeCspHandle provider,
                               SafeCapiKeyHandle key,
                               byte[] iv,
                               CipherMode cipherMode,
                               PaddingMode paddingMode,
                               EncryptionMode encryptionMode) {
     Contract.Requires(0 < blockSize && blockSize % 8 == 0);
     Contract.Requires(0 <= feedbackSize);
     Contract.Requires(provider != null && !provider.IsInvalid && !provider.IsClosed);
     Contract.Requires(key != null && !key.IsInvalid && !key.IsClosed);
     Contract.Ensures(m_provider != null && !m_provider.IsInvalid && !m_provider.IsClosed);
     
     m_blockSize = blockSize;
     m_encryptionMode = encryptionMode;
     m_paddingMode = paddingMode;
     m_provider = provider.Duplicate();
     m_key = SetupKey(key, ProcessIV(iv, blockSize, cipherMode), cipherMode, feedbackSize);
 }
コード例 #10
0
        public CapiSymmetricAlgorithm(int blockSize,
                                      int feedbackSize,
                                      Microsoft.Win32.SafeHandles.SafeCspHandle provider,
                                      SafeCapiKeyHandle key,
                                      byte[] iv,
                                      CipherMode cipherMode,
                                      PaddingMode paddingMode,
                                      EncryptionMode encryptionMode)
        {
            Contract.Requires(0 < blockSize && blockSize % 8 == 0);
            Contract.Requires(0 <= feedbackSize);
            Contract.Requires(provider != null && !provider.IsInvalid && !provider.IsClosed);
            Contract.Requires(key != null && !key.IsInvalid && !key.IsClosed);
            Contract.Ensures(m_provider != null && !m_provider.IsInvalid && !m_provider.IsClosed);

            m_blockSize      = blockSize;
            m_encryptionMode = encryptionMode;
            m_paddingMode    = paddingMode;
            m_provider       = provider.Duplicate();
            m_key            = SetupKey(key, ProcessIV(iv, blockSize, cipherMode), cipherMode, feedbackSize);
        }
コード例 #11
0
        public AesCryptoServiceProvider()
        {
            Contract.Ensures(m_cspHandle != null && !m_cspHandle.IsInvalid && !m_cspHandle.IsClosed);

            // On Windows XP the AES CSP has the prototype name, but on newer operating systems it has the
            // standard name
            string providerName = CapiNative.ProviderNames.MicrosoftEnhancedRsaAes;

            if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor == 1)
            {
                providerName = CapiNative.ProviderNames.MicrosoftEnhancedRsaAesPrototype;
            }

            m_cspHandle = CapiNative.AcquireCsp(null,
                                                providerName,
                                                CapiNative.ProviderType.RsaAes,
                                                CapiNative.CryptAcquireContextFlags.VerifyContext,
                                                true);

            // CAPI will not allow feedback sizes greater than 64 bits
            FeedbackSizeValue = 8;

            // Get the different AES key sizes supported by this platform, raising an error if there are no
            // supported key sizes.
            int defaultKeySize = 0;

            KeySizes[] keySizes = FindSupportedKeySizes(m_cspHandle, out defaultKeySize);
            if (keySizes.Length != 0)
            {
                Debug.Assert(defaultKeySize > 0, "defaultKeySize > 0");
                KeySizeValue = defaultKeySize;
            }
            else
            {
                throw new PlatformNotSupportedException(SR.GetString(SR.Cryptography_PlatformNotSupported));
            }
        }
コード例 #12
0
 public static extern bool CryptImportKey(Microsoft.Win32.SafeHandles.SafeCspHandle hProv,
                                          [MarshalAs(UnmanagedType.LPArray)] byte[] pbData,
                                          int dwDataLen,
                                          SafeCapiKeyHandle hPubKey,
                                          KeyFlags dwFlags,
                                          [Out] out SafeCapiKeyHandle phKey);
コード例 #13
0
 public static extern bool CryptGetProvParam(Microsoft.Win32.SafeHandles.SafeCspHandle hProv,
                                             ProviderParameter dwParam,
                                             IntPtr pbData,
                                             [In, Out] ref int pdwDataLen,
                                             ProviderParameterFlags dwFlags);
コード例 #14
0
 public static extern bool CryptGenRandom(Microsoft.Win32.SafeHandles.SafeCspHandle hProv,
                                          int dwLen,
                                          [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbBuffer);
コード例 #15
0
 public static extern bool CryptGenKey(Microsoft.Win32.SafeHandles.SafeCspHandle hProv,
                                       AlgorithmId Algid,
                                       KeyFlags dwFlags,
                                       [Out] out SafeCapiKeyHandle phKey);
コード例 #16
0
 public static extern bool CryptCreateHash(Microsoft.Win32.SafeHandles.SafeCspHandle hProv,
                                           AlgorithmId Algid,
                                           SafeCapiKeyHandle hKey,
                                           int dwFlags,
                                           [Out] out SafeCapiHashHandle phHash);
コード例 #17
0
        internal static SafeCapiKeyHandle ImportSymmetricKey(Microsoft.Win32.SafeHandles.SafeCspHandle provider, AlgorithmId algorithm, byte[] key)
        {
            Contract.Requires(provider != null);
            Contract.Requires(((int)algorithm & (int)AlgorithmClass.DataEncryption) == (int)AlgorithmClass.DataEncryption);
            Contract.Requires(key != null);
            Contract.Ensures(Contract.Result <SafeCapiKeyHandle>() != null &&
                             !Contract.Result <SafeCapiKeyHandle>().IsInvalid&&
                             !Contract.Result <SafeCapiKeyHandle>().IsClosed);

            //
            // Setup a PLAINTEXTKEYBLOB (v2) which has the following format:
            //   BLOBHEADER hdr
            //   DWORD      cbKeySize
            //   BYTE       rbgKeyData[]
            //

            int blobSize = Marshal.SizeOf(typeof(BLOBHEADER)) + Marshal.SizeOf(typeof(int)) + key.Length;

            byte[] keyBlob = new byte[blobSize];

            unsafe
            {
                fixed(byte *pBlob = keyBlob)
                {
                    BLOBHEADER *pHeader = (BLOBHEADER *)pBlob;

                    pHeader->bType    = KeyBlobType.PlainText;
                    pHeader->bVersion = 2;
                    pHeader->reserved = 0;
                    pHeader->aiKeyAlg = algorithm;

                    int *pSize = (int *)(pBlob + Marshal.SizeOf(*pHeader));

                    *pSize = key.Length;
                }
            }

            Buffer.BlockCopy(key, 0, keyBlob, Marshal.SizeOf(typeof(BLOBHEADER)) + Marshal.SizeOf(typeof(int)), key.Length);

            // Import the PLAINTEXTKEYBLOB into the CSP
            SafeCapiKeyHandle importedKey = null;

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                if (!UnsafeNativeMethods.CryptImportKey(provider,
                                                        keyBlob,
                                                        keyBlob.Length,
                                                        SafeCapiKeyHandle.InvalidHandle,
                                                        KeyFlags.Exportable,
                                                        out importedKey))
                {
                    throw new CryptographicException(Marshal.GetLastWin32Error());
                }
            }
            finally {
                if (importedKey != null && !importedKey.IsInvalid)
                {
                    importedKey.SetParentCsp(provider);
                }
            }
            return(importedKey);
        }
コード例 #18
0
 private static extern bool CryptContextAddRef(SafeCspHandle hProv, IntPtr pdwReserved, int dwFlags);
コード例 #19
0
 public static extern bool CryptAcquireContext([Out] out Microsoft.Win32.SafeHandles.SafeCspHandle phProv,
                                               string pszContainer,
                                               string pszProvider,
                                               ProviderType dwProvType,
                                               CryptAcquireContextFlags dwFlags);
コード例 #20
0
        private static KeySizes[] FindSupportedKeySizes(Microsoft.Win32.SafeHandles.SafeCspHandle csp, out int defaultKeySize)
        {
            Contract.Requires(csp != null);
            Contract.Ensures(Contract.Result <KeySizes[]>() != null);

            // If this platform has any supported algorithm sizes, then the default key size should be set to a
            // reasonable value.
            Contract.Ensures(Contract.Result <KeySizes[]>().Length == 0 ||
                             (Contract.ValueAtReturn <int>(out defaultKeySize) > 0 && Contract.ValueAtReturn <int>(out defaultKeySize) % 8 == 0));

            if (s_supportedKeySizes == null)
            {
                List <KeySizes> keySizes   = new List <KeySizes>();
                int             maxKeySize = 0;

                //
                // Enumerate the CSP's supported algorithms to see what key sizes it supports for AES
                //

                CapiNative.PROV_ENUMALGS algorithm =
                    CapiNative.GetProviderParameterStruct <CapiNative.PROV_ENUMALGS>(csp,
                                                                                     CapiNative.ProviderParameter.EnumerateAlgorithms,
                                                                                     CapiNative.ProviderParameterFlags.RestartEnumeration);

                // Translate between CAPI AES algorithm IDs and supported key sizes
                while (algorithm.aiAlgId != CapiNative.AlgorithmId.None)
                {
                    switch (algorithm.aiAlgId)
                    {
                    case CapiNative.AlgorithmId.Aes128:
                        keySizes.Add(new KeySizes(128, 128, 0));
                        if (128 > maxKeySize)
                        {
                            maxKeySize = 128;
                        }

                        break;

                    case CapiNative.AlgorithmId.Aes192:
                        keySizes.Add(new KeySizes(192, 192, 0));
                        if (192 > maxKeySize)
                        {
                            maxKeySize = 192;
                        }
                        break;

                    case CapiNative.AlgorithmId.Aes256:
                        keySizes.Add(new KeySizes(256, 256, 0));
                        if (256 > maxKeySize)
                        {
                            maxKeySize = 256;
                        }
                        break;

                    default:
                        break;
                    }

                    algorithm = CapiNative.GetProviderParameterStruct <CapiNative.PROV_ENUMALGS>(csp,
                                                                                                 CapiNative.ProviderParameter.EnumerateAlgorithms,
                                                                                                 CapiNative.ProviderParameterFlags.None);
                }

                s_supportedKeySizes = keySizes.ToArray();
                s_defaultKeySize    = maxKeySize;
            }

            defaultKeySize = s_defaultKeySize;
            return(s_supportedKeySizes);
        }