/* * Mentalis.org Security Library * * Copyright © 2002-2005, The KPD-Team * All rights reserved. * http://www.mentalis.org/ * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Neither the name of the KPD-Team, nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ using System; using System.Runtime.InteropServices; using System.Security.Cryptography; namespace Org.Mentalis.Security.Cryptography { internal class CAPIProvider { internal CAPIProvider() {} public static int Handle { get { m_Provider.CreateInternalHandle(ref m_Provider.m_Handle, null); return m_Provider.m_Handle; } } public static int HandleProviderType { get { m_Provider.CreateInternalHandle(ref m_Provider.m_Handle, null); return m_Provider.m_HandleProviderType; } } public static int ContainerHandle { get { m_Provider.CreateInternalHandle(ref m_Provider.m_ContainerHandle, SecurityConstants.KEY_CONTAINER); return m_Provider.m_ContainerHandle; } } public void CreateInternalHandle(ref int handle, string container) { if (handle == 0) { lock(this) { if (handle == 0 && !m_Error) { int flags, fs = 0, fmk = 0; if (!Environment.UserInteractive && Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 5) { fs = SecurityConstants.CRYPT_SILENT; fmk = SecurityConstants.CRYPT_MACHINE_KEYSET; } for(int i = 0; i < m_Providers.Length; i++) { flags = fs | fmk; m_HandleProviderType = m_Providers[i]; if (SspiProvider.CryptAcquireContext(ref handle, container, null, m_Providers[i], flags) == 0) { if (Marshal.GetLastWin32Error() == SecurityConstants.NTE_BAD_KEYSET) { SspiProvider.CryptAcquireContext(ref handle, container, null, m_Providers[i], flags | SecurityConstants.CRYPT_NEWKEYSET); } else if(fmk != 0) { flags = fs; if (SspiProvider.CryptAcquireContext(ref handle, container, null, m_Providers[i], flags) == 0) { if (Marshal.GetLastWin32Error() == SecurityConstants.NTE_BAD_KEYSET) { SspiProvider.CryptAcquireContext(ref handle, container, null, m_Providers[i], flags | SecurityConstants.CRYPT_NEWKEYSET); } } } } if (handle != 0) break; } if (handle == 0) { m_Error = true; m_HandleProviderType = 0; } } if (m_Error) throw new CryptographicException("Couldn't acquire crypto service provider context."); } } } ~CAPIProvider() { if (m_Handle != 0) SspiProvider.CryptReleaseContext(m_Handle, 0); if (m_ContainerHandle != 0) SspiProvider.CryptReleaseContext(m_ContainerHandle, 0); } private int m_Handle = 0; private int m_ContainerHandle = 0; private bool m_Error = false; private int m_HandleProviderType = 0; private static int[] m_Providers = new int[] {SecurityConstants.PROV_RSA_AES, SecurityConstants.PROV_RSA_FULL}; private static CAPIProvider m_Provider = new CAPIProvider(); } /// /// Specifies the type of encryption method to use when protecting data. /// public enum ProtectionType { /// The encrypted data is associated with the local machine. Any user on the computer on which the data is encrypted can decrypt the data. LocalMachine, /// The encrypted data is associated with the current user. Only a user with logon credentials matching those of the encrypter can decrypt the data. CurrentUser } /// /// Specifies the type of algorithm to be used when performing unmanaged cryptographic transformations. /// internal enum CryptoAlgorithm : int { /// The Rijndael algorithm with a key size of 128 bits. Rijndael128 = SecurityConstants.CALG_AES_128, /// The Rijndael algorithm with a key size of 192 bits. Rijndael192 = SecurityConstants.CALG_AES_192, /// The Rijndael algorithm with a key size of 256 bits. Rijndael256 = SecurityConstants.CALG_AES_256, /// The RC4 algorithm. RC4 = SecurityConstants.CALG_RC4 } /// /// Specifies the type of CSP to be used when performing unmanaged cryptographic transformations. /// internal enum CryptoProvider { /// Microsoft's full RSA CSP. RsaFull = SecurityConstants.PROV_RSA_FULL, /// Microsoft's full RSA CSP that supports the AES. RsaAes = SecurityConstants.PROV_RSA_AES } /// /// Specifies the type of transformation for a cryptographic operation. /// internal enum CryptoMethod { /// Encrypt the data. Encrypt, /// Decrypt the data. Decrypt } /// /// The PUBLICKEYSTRUC structure, also known as the BLOBHEADER structure, indicates a key's BLOB type and the algorithm that the key uses. One of these structures is located at the beginning of the pbData member of every key BLOB. /// [StructLayout(LayoutKind.Sequential)] internal struct PUBLICKEYSTRUC { /// Key BLOB type. The only BLOB types currently defined are PUBLICKEYBLOB, PRIVATEKEYBLOB, SIMPLEBLOB, and PLAINTEXTBLOB. Other key BLOB types will be defined as needed. public byte bType; /// Version number of the key BLOB format. This currently must always have a value of CUR_BLOB_VERSION (0x02). public byte bVersion; /// WORD reserved for future use. Must be set to zero. public short reserved; /// Algorithm identifier for the key contained by the key BLOB. Some examples are CALG_RSA_SIGN, CALG_RSA_KEYX, CALG_RC2, and CALG_RC4. public IntPtr aiKeyAlg; } }