Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / security / system / security / cryptography / x509 / X509Utils.cs / 1 / X509Utils.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // // X509Utils.cs // namespace System.Security.Cryptography.X509Certificates { using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; internal class X509Utils { private X509Utils () {} internal static bool IsCertRdnCharString (uint dwValueType) { return ((dwValueType & CAPI.CERT_RDN_TYPE_MASK) >= CAPI.CERT_RDN_NUMERIC_STRING); } // this method maps a cert content type returned from CryptQueryObject // to a value in the managed X509ContentType enum internal static X509ContentType MapContentType (uint contentType) { switch (contentType) { case CAPI.CERT_QUERY_CONTENT_CERT: return X509ContentType.Cert; case CAPI.CERT_QUERY_CONTENT_SERIALIZED_STORE: return X509ContentType.SerializedStore; case CAPI.CERT_QUERY_CONTENT_SERIALIZED_CERT: return X509ContentType.SerializedCert; case CAPI.CERT_QUERY_CONTENT_PKCS7_SIGNED: case CAPI.CERT_QUERY_CONTENT_PKCS7_UNSIGNED: return X509ContentType.Pkcs7; case CAPI.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED: return X509ContentType.Authenticode; case CAPI.CERT_QUERY_CONTENT_PFX: return X509ContentType.Pkcs12; default: return X509ContentType.Unknown; } } // this method maps a X509KeyStorageFlags enum to a combination of crypto API flags internal static uint MapKeyStorageFlags (X509KeyStorageFlags keyStorageFlags) { uint dwFlags = 0; if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet) dwFlags |= CAPI.CRYPT_USER_KEYSET; else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet) dwFlags |= CAPI.CRYPT_MACHINE_KEYSET; if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable) dwFlags |= CAPI.CRYPT_EXPORTABLE; if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected) dwFlags |= CAPI.CRYPT_USER_PROTECTED; return dwFlags; } // this method maps X509Store OpenFlags to a combination of crypto API flags internal static uint MapX509StoreFlags (StoreLocation storeLocation, OpenFlags flags) { uint dwFlags = 0; uint openMode = ((uint)flags) & 0x3; switch (openMode) { case (uint) OpenFlags.ReadOnly: dwFlags |= CAPI.CERT_STORE_READONLY_FLAG; break; case (uint) OpenFlags.MaxAllowed: dwFlags |= CAPI.CERT_STORE_MAXIMUM_ALLOWED_FLAG; break; } if ((flags & OpenFlags.OpenExistingOnly) == OpenFlags.OpenExistingOnly) dwFlags |= CAPI.CERT_STORE_OPEN_EXISTING_FLAG; if ((flags & OpenFlags.IncludeArchived) == OpenFlags.IncludeArchived) dwFlags |= CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG; if (storeLocation == StoreLocation.LocalMachine) dwFlags |= CAPI.CERT_SYSTEM_STORE_LOCAL_MACHINE; else if (storeLocation == StoreLocation.CurrentUser) dwFlags |= CAPI.CERT_SYSTEM_STORE_CURRENT_USER; return dwFlags; } // this method maps an X509NameType to crypto API flags. internal static uint MapNameType (X509NameType nameType) { uint type = 0; switch (nameType) { case X509NameType.SimpleName: type = CAPI.CERT_NAME_SIMPLE_DISPLAY_TYPE; break; case X509NameType.EmailName: type = CAPI.CERT_NAME_EMAIL_TYPE; break; case X509NameType.UpnName: type = CAPI.CERT_NAME_UPN_TYPE; break; case X509NameType.DnsName: case X509NameType.DnsFromAlternativeName: type = CAPI.CERT_NAME_DNS_TYPE; break; case X509NameType.UrlName: type = CAPI.CERT_NAME_URL_TYPE; break; default: throw new ArgumentException(SR.GetString(SR.Argument_InvalidNameType)); } return type; } // this method maps X509RevocationFlag to crypto API flags. internal static uint MapRevocationFlags (X509RevocationMode revocationMode, X509RevocationFlag revocationFlag) { uint dwFlags = 0; if (revocationMode == X509RevocationMode.NoCheck) return dwFlags; if (revocationMode == X509RevocationMode.Offline) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; if (revocationFlag == X509RevocationFlag.EndCertificateOnly) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_END_CERT; else if (revocationFlag == X509RevocationFlag.EntireChain) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CHAIN; else dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; return dwFlags; } private static readonly char[] hexValues = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; internal static string EncodeHexString (byte[] sArray) { return EncodeHexString(sArray, 0, (uint) sArray.Length); } internal static string EncodeHexString (byte[] sArray, uint start, uint end) { String result = null; if (sArray != null) { char[] hexOrder = new char[(end - start) * 2]; uint digit; for (uint i = start, j = 0; i < end; i++) { digit = (uint) ((sArray[i] & 0xf0) >> 4); hexOrder[j++] = hexValues[digit]; digit = (uint) (sArray[i] & 0x0f); hexOrder[j++] = hexValues[digit]; } result = new String(hexOrder); } return result; } internal static string EncodeHexStringFromInt (byte[] sArray, uint start, uint end) { String result = null; if(sArray != null) { char[] hexOrder = new char[(end - start) * 2]; uint i = end; uint digit, j=0; while (i-- > start) { digit = (uint) (sArray[i] & 0xf0) >> 4; hexOrder[j++] = hexValues[digit]; digit = (uint) (sArray[i] & 0x0f); hexOrder[j++] = hexValues[digit]; } result = new String(hexOrder); } return result; } internal static byte HexToByte (char val) { if (val <= '9' && val >= '0') return (byte) (val - '0'); else if (val >= 'a' && val <= 'f') return (byte) ((val - 'a') + 10); else if (val >= 'A' && val <= 'F') return (byte) ((val - 'A') + 10); else return 0xFF; } internal static uint AlignedLength (uint length) { return ((length + (uint) 7) & ((uint) 0xfffffff8)); } internal static String DiscardWhiteSpaces (string inputBuffer) { return DiscardWhiteSpaces(inputBuffer, 0, inputBuffer.Length); } internal static String DiscardWhiteSpaces (string inputBuffer, int inputOffset, int inputCount) { int i, iCount = 0; for (i=0; i0) { if (hex[index] != 0) break; } return index + 1; } internal static SafeLocalAllocHandle ByteToPtr (byte[] managed) { SafeLocalAllocHandle pb = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(managed.Length)); Marshal.Copy(managed, 0, pb.DangerousGetHandle(), managed.Length); return pb; } // // This method copies an unmanaged structure into the address of a managed structure. // This is useful when the structure is returned to us by Crypto API and its size varies // following the platform. // internal unsafe static void memcpy (IntPtr source, IntPtr dest, uint size) { for (uint index = 0; index < size; index++) { *(byte*) ((long)dest + index) = Marshal.ReadByte(new IntPtr((long)source + index)); } } internal static byte[] PtrToByte (IntPtr unmanaged, uint size) { byte[] array = new byte[(int) size]; Marshal.Copy(unmanaged, array, 0, array.Length); return array; } internal static unsafe bool MemEqual (byte * pbBuf1, uint cbBuf1, byte * pbBuf2, uint cbBuf2) { if (cbBuf1 != cbBuf2) return false; while (cbBuf1-- > 0) { if (*pbBuf1++ != *pbBuf2++) { return false; } } return true; } internal static SafeLocalAllocHandle StringToAnsiPtr (string s) { byte[] arr = new byte[s.Length + 1]; Encoding.ASCII.GetBytes(s, 0, s.Length, arr, 0); SafeLocalAllocHandle pb = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(arr.Length)); Marshal.Copy(arr, 0, pb.DangerousGetHandle(), arr.Length); return pb; } internal static SafeLocalAllocHandle StringToUniPtr (string s) { byte[] arr = new byte[2 * (s.Length + 1)]; Encoding.Unicode.GetBytes(s, 0, s.Length, arr, 0); SafeLocalAllocHandle pb = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(arr.Length)); Marshal.Copy(arr, 0, pb.DangerousGetHandle(), arr.Length); return pb; } // this method create a memory store from a certificate collection internal static SafeCertStoreHandle ExportToMemoryStore (X509Certificate2Collection collection) { // // We need to Assert all StorePermission flags since this is a memory store and we want // semi-trusted code to be able to export certificates to a memory store. // StorePermission sp = new StorePermission(StorePermissionFlags.AllFlags); sp.Assert(); SafeCertStoreHandle safeCertStoreHandle = SafeCertStoreHandle.InvalidHandle; // we always want to use CERT_STORE_ENUM_ARCHIVED_FLAG since we want to preserve the collection in this operation. // By default, Archived certificates will not be included. safeCertStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); // // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get // applied to the original store. This has a limit of 99 links per cert context however. // foreach (X509Certificate2 x509 in collection) { if (!CAPI.CertAddCertificateLinkToStore(safeCertStoreHandle, x509.CertContext, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) throw new CryptographicException(Marshal.GetLastWin32Error()); } return safeCertStoreHandle; } internal static uint OidToAlgId (string value) { SafeLocalAllocHandle pszOid = StringToAnsiPtr(value); CAPI.CRYPT_OID_INFO pOIDInfo = CAPI.CryptFindOIDInfo(CAPI.CRYPT_OID_INFO_OID_KEY, pszOid, 0); return pOIDInfo.Algid; } internal static string FindOidInfo(uint keyType, string keyValue, OidGroup oidGroup) { Debug.Assert(OidGroup.AllGroups <= oidGroup && oidGroup <= OidGroup.Template, "Invalid OID group"); if (keyValue == null) throw new ArgumentNullException("keyValue"); if (keyValue.Length == 0) return null; SafeLocalAllocHandle pvKey = SafeLocalAllocHandle.InvalidHandle; switch(keyType) { case CAPI.CRYPT_OID_INFO_OID_KEY: pvKey = StringToAnsiPtr(keyValue); break; case CAPI.CRYPT_OID_INFO_NAME_KEY: pvKey = StringToUniPtr(keyValue); break; default: Debug.Assert(false); break; } CAPI.CRYPT_OID_INFO pOidInfo = CAPI.CryptFindOIDInfo(keyType, pvKey, oidGroup); // if we couldn't find the OID within a specific group, retry with the generic group if(pOidInfo.pszOID == null && oidGroup != OidGroup.AllGroups) pOidInfo = CAPI.CryptFindOIDInfo(keyType, pvKey, OidGroup.AllGroups); if (keyType == CAPI.CRYPT_OID_INFO_OID_KEY) return pOidInfo.pwszName; else return pOidInfo.pszOID; } // // verify the passed keyValue is valid as per X.208 // // The first number must be 0, 1 or 2. // Enforce all characters are digits and dots. // Enforce that no dot starts or ends the Oid, and disallow double dots. // Enforce there is at least one dot separator. // internal static void ValidateOidValue (string keyValue) { if (keyValue == null) throw new ArgumentNullException("keyValue"); int len = keyValue.Length; if (len < 2) goto error; // should not start with a dot. The first digit must be 0, 1 or 2. char c = keyValue[0]; if (c != '0' && c != '1' && c != '2') goto error; if (keyValue[1] != '.' || keyValue[len - 1] == '.') // should not end in a dot goto error; bool hasAtLeastOneDot = false; for (int i = 1; i < len; i++) { // ensure every character is either a digit or a dot if (Char.IsDigit(keyValue[i])) continue; if (keyValue[i] != '.' || keyValue[i + 1] == '.') // disallow double dots goto error; hasAtLeastOneDot = true; } if (hasAtLeastOneDot) return; error: throw new ArgumentException(SR.GetString(SR.Argument_InvalidOidValue)); } internal static SafeLocalAllocHandle CopyOidsToUnmanagedMemory (OidCollection oids) { SafeLocalAllocHandle safeLocalAllocHandle = SafeLocalAllocHandle.InvalidHandle; if (oids == null || oids.Count == 0) return safeLocalAllocHandle; int ptrSize = oids.Count * Marshal.SizeOf(typeof(IntPtr)); int oidSize = 0; foreach (Oid oid in oids) { oidSize += (oid.Value.Length + 1); } safeLocalAllocHandle = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr((uint) ptrSize + (uint) oidSize)); IntPtr pOid = new IntPtr((long)safeLocalAllocHandle.DangerousGetHandle() + ptrSize); for (int index=0; index < oids.Count; index++) { Marshal.WriteIntPtr(new IntPtr((long) safeLocalAllocHandle.DangerousGetHandle() + index * Marshal.SizeOf(typeof(IntPtr))), pOid); byte[] ansiOid = Encoding.ASCII.GetBytes(oids[index].Value); Marshal.Copy(ansiOid, 0, pOid, ansiOid.Length); pOid = new IntPtr((long) pOid + oids[index].Value.Length + 1); } return safeLocalAllocHandle; } internal static X509Certificate2Collection GetCertificates(SafeCertStoreHandle safeCertStoreHandle) { X509Certificate2Collection collection = new X509Certificate2Collection(); IntPtr pEnumContext = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, IntPtr.Zero); while (pEnumContext != IntPtr.Zero) { X509Certificate2 certificate = new X509Certificate2(pEnumContext); collection.Add(certificate); pEnumContext = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, pEnumContext); } return collection; } // // Verifies whether a certificate is valid for the specified policy. // S_OK means the certificate is valid for the specified policy. // S_FALSE means the certificate is invalid for the specified policy. // Anything else is an error. // internal static unsafe int VerifyCertificate (SafeCertContextHandle pCertContext, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout, X509Certificate2Collection extraStore, IntPtr pszPolicy, IntPtr pdwErrorStatus) { if (pCertContext == null || pCertContext.IsInvalid) throw new ArgumentException("pCertContext"); CAPI.CERT_CHAIN_POLICY_PARA PolicyPara = new CAPI.CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_PARA))); CAPI.CERT_CHAIN_POLICY_STATUS PolicyStatus = new CAPI.CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_STATUS))); // Build the chain. SafeCertChainHandle pChainContext = SafeCertChainHandle.InvalidHandle; int hr = X509Chain.BuildChain(new IntPtr(CAPI.HCCE_CURRENT_USER), pCertContext, extraStore, applicationPolicy, certificatePolicy, revocationMode, revocationFlag, verificationTime, timeout, ref pChainContext); if (hr != CAPI.S_OK) return hr; // Verify the chain using the specified policy. if (CAPI.CertVerifyCertificateChainPolicy(pszPolicy, pChainContext, ref PolicyPara, ref PolicyStatus)) { if (pdwErrorStatus != IntPtr.Zero) *(uint*) pdwErrorStatus = PolicyStatus.dwError; if (PolicyStatus.dwError != 0) return CAPI.S_FALSE; } else { // The API failed. return Marshal.GetHRForLastWin32Error(); } return CAPI.S_OK; } internal static string GetSystemErrorString (int hr) { StringBuilder strMessage = new StringBuilder(512); uint dwErrorCode = CAPI.FormatMessage (CAPI.FORMAT_MESSAGE_FROM_SYSTEM | CAPI.FORMAT_MESSAGE_IGNORE_INSERTS, IntPtr.Zero, (uint) hr, CAPI.GetUserDefaultLCID(), strMessage, 511, IntPtr.Zero); if (dwErrorCode != 0) return strMessage.ToString(); else return SR.GetString(SR.Unknown_Error); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // // X509Utils.cs // namespace System.Security.Cryptography.X509Certificates { using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; internal class X509Utils { private X509Utils () {} internal static bool IsCertRdnCharString (uint dwValueType) { return ((dwValueType & CAPI.CERT_RDN_TYPE_MASK) >= CAPI.CERT_RDN_NUMERIC_STRING); } // this method maps a cert content type returned from CryptQueryObject // to a value in the managed X509ContentType enum internal static X509ContentType MapContentType (uint contentType) { switch (contentType) { case CAPI.CERT_QUERY_CONTENT_CERT: return X509ContentType.Cert; case CAPI.CERT_QUERY_CONTENT_SERIALIZED_STORE: return X509ContentType.SerializedStore; case CAPI.CERT_QUERY_CONTENT_SERIALIZED_CERT: return X509ContentType.SerializedCert; case CAPI.CERT_QUERY_CONTENT_PKCS7_SIGNED: case CAPI.CERT_QUERY_CONTENT_PKCS7_UNSIGNED: return X509ContentType.Pkcs7; case CAPI.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED: return X509ContentType.Authenticode; case CAPI.CERT_QUERY_CONTENT_PFX: return X509ContentType.Pkcs12; default: return X509ContentType.Unknown; } } // this method maps a X509KeyStorageFlags enum to a combination of crypto API flags internal static uint MapKeyStorageFlags (X509KeyStorageFlags keyStorageFlags) { uint dwFlags = 0; if ((keyStorageFlags & X509KeyStorageFlags.UserKeySet) == X509KeyStorageFlags.UserKeySet) dwFlags |= CAPI.CRYPT_USER_KEYSET; else if ((keyStorageFlags & X509KeyStorageFlags.MachineKeySet) == X509KeyStorageFlags.MachineKeySet) dwFlags |= CAPI.CRYPT_MACHINE_KEYSET; if ((keyStorageFlags & X509KeyStorageFlags.Exportable) == X509KeyStorageFlags.Exportable) dwFlags |= CAPI.CRYPT_EXPORTABLE; if ((keyStorageFlags & X509KeyStorageFlags.UserProtected) == X509KeyStorageFlags.UserProtected) dwFlags |= CAPI.CRYPT_USER_PROTECTED; return dwFlags; } // this method maps X509Store OpenFlags to a combination of crypto API flags internal static uint MapX509StoreFlags (StoreLocation storeLocation, OpenFlags flags) { uint dwFlags = 0; uint openMode = ((uint)flags) & 0x3; switch (openMode) { case (uint) OpenFlags.ReadOnly: dwFlags |= CAPI.CERT_STORE_READONLY_FLAG; break; case (uint) OpenFlags.MaxAllowed: dwFlags |= CAPI.CERT_STORE_MAXIMUM_ALLOWED_FLAG; break; } if ((flags & OpenFlags.OpenExistingOnly) == OpenFlags.OpenExistingOnly) dwFlags |= CAPI.CERT_STORE_OPEN_EXISTING_FLAG; if ((flags & OpenFlags.IncludeArchived) == OpenFlags.IncludeArchived) dwFlags |= CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG; if (storeLocation == StoreLocation.LocalMachine) dwFlags |= CAPI.CERT_SYSTEM_STORE_LOCAL_MACHINE; else if (storeLocation == StoreLocation.CurrentUser) dwFlags |= CAPI.CERT_SYSTEM_STORE_CURRENT_USER; return dwFlags; } // this method maps an X509NameType to crypto API flags. internal static uint MapNameType (X509NameType nameType) { uint type = 0; switch (nameType) { case X509NameType.SimpleName: type = CAPI.CERT_NAME_SIMPLE_DISPLAY_TYPE; break; case X509NameType.EmailName: type = CAPI.CERT_NAME_EMAIL_TYPE; break; case X509NameType.UpnName: type = CAPI.CERT_NAME_UPN_TYPE; break; case X509NameType.DnsName: case X509NameType.DnsFromAlternativeName: type = CAPI.CERT_NAME_DNS_TYPE; break; case X509NameType.UrlName: type = CAPI.CERT_NAME_URL_TYPE; break; default: throw new ArgumentException(SR.GetString(SR.Argument_InvalidNameType)); } return type; } // this method maps X509RevocationFlag to crypto API flags. internal static uint MapRevocationFlags (X509RevocationMode revocationMode, X509RevocationFlag revocationFlag) { uint dwFlags = 0; if (revocationMode == X509RevocationMode.NoCheck) return dwFlags; if (revocationMode == X509RevocationMode.Offline) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY; if (revocationFlag == X509RevocationFlag.EndCertificateOnly) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_END_CERT; else if (revocationFlag == X509RevocationFlag.EntireChain) dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CHAIN; else dwFlags |= CAPI.CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; return dwFlags; } private static readonly char[] hexValues = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; internal static string EncodeHexString (byte[] sArray) { return EncodeHexString(sArray, 0, (uint) sArray.Length); } internal static string EncodeHexString (byte[] sArray, uint start, uint end) { String result = null; if (sArray != null) { char[] hexOrder = new char[(end - start) * 2]; uint digit; for (uint i = start, j = 0; i < end; i++) { digit = (uint) ((sArray[i] & 0xf0) >> 4); hexOrder[j++] = hexValues[digit]; digit = (uint) (sArray[i] & 0x0f); hexOrder[j++] = hexValues[digit]; } result = new String(hexOrder); } return result; } internal static string EncodeHexStringFromInt (byte[] sArray, uint start, uint end) { String result = null; if(sArray != null) { char[] hexOrder = new char[(end - start) * 2]; uint i = end; uint digit, j=0; while (i-- > start) { digit = (uint) (sArray[i] & 0xf0) >> 4; hexOrder[j++] = hexValues[digit]; digit = (uint) (sArray[i] & 0x0f); hexOrder[j++] = hexValues[digit]; } result = new String(hexOrder); } return result; } internal static byte HexToByte (char val) { if (val <= '9' && val >= '0') return (byte) (val - '0'); else if (val >= 'a' && val <= 'f') return (byte) ((val - 'a') + 10); else if (val >= 'A' && val <= 'F') return (byte) ((val - 'A') + 10); else return 0xFF; } internal static uint AlignedLength (uint length) { return ((length + (uint) 7) & ((uint) 0xfffffff8)); } internal static String DiscardWhiteSpaces (string inputBuffer) { return DiscardWhiteSpaces(inputBuffer, 0, inputBuffer.Length); } internal static String DiscardWhiteSpaces (string inputBuffer, int inputOffset, int inputCount) { int i, iCount = 0; for (i=0; i 0) { if (hex[index] != 0) break; } return index + 1; } internal static SafeLocalAllocHandle ByteToPtr (byte[] managed) { SafeLocalAllocHandle pb = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(managed.Length)); Marshal.Copy(managed, 0, pb.DangerousGetHandle(), managed.Length); return pb; } // // This method copies an unmanaged structure into the address of a managed structure. // This is useful when the structure is returned to us by Crypto API and its size varies // following the platform. // internal unsafe static void memcpy (IntPtr source, IntPtr dest, uint size) { for (uint index = 0; index < size; index++) { *(byte*) ((long)dest + index) = Marshal.ReadByte(new IntPtr((long)source + index)); } } internal static byte[] PtrToByte (IntPtr unmanaged, uint size) { byte[] array = new byte[(int) size]; Marshal.Copy(unmanaged, array, 0, array.Length); return array; } internal static unsafe bool MemEqual (byte * pbBuf1, uint cbBuf1, byte * pbBuf2, uint cbBuf2) { if (cbBuf1 != cbBuf2) return false; while (cbBuf1-- > 0) { if (*pbBuf1++ != *pbBuf2++) { return false; } } return true; } internal static SafeLocalAllocHandle StringToAnsiPtr (string s) { byte[] arr = new byte[s.Length + 1]; Encoding.ASCII.GetBytes(s, 0, s.Length, arr, 0); SafeLocalAllocHandle pb = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(arr.Length)); Marshal.Copy(arr, 0, pb.DangerousGetHandle(), arr.Length); return pb; } internal static SafeLocalAllocHandle StringToUniPtr (string s) { byte[] arr = new byte[2 * (s.Length + 1)]; Encoding.Unicode.GetBytes(s, 0, s.Length, arr, 0); SafeLocalAllocHandle pb = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(arr.Length)); Marshal.Copy(arr, 0, pb.DangerousGetHandle(), arr.Length); return pb; } // this method create a memory store from a certificate collection internal static SafeCertStoreHandle ExportToMemoryStore (X509Certificate2Collection collection) { // // We need to Assert all StorePermission flags since this is a memory store and we want // semi-trusted code to be able to export certificates to a memory store. // StorePermission sp = new StorePermission(StorePermissionFlags.AllFlags); sp.Assert(); SafeCertStoreHandle safeCertStoreHandle = SafeCertStoreHandle.InvalidHandle; // we always want to use CERT_STORE_ENUM_ARCHIVED_FLAG since we want to preserve the collection in this operation. // By default, Archived certificates will not be included. safeCertStoreHandle = CAPI.CertOpenStore(new IntPtr(CAPI.CERT_STORE_PROV_MEMORY), CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, IntPtr.Zero, CAPI.CERT_STORE_ENUM_ARCHIVED_FLAG | CAPI.CERT_STORE_CREATE_NEW_FLAG, null); if (safeCertStoreHandle == null || safeCertStoreHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); // // We use CertAddCertificateLinkToStore to keep a link to the original store, so any property changes get // applied to the original store. This has a limit of 99 links per cert context however. // foreach (X509Certificate2 x509 in collection) { if (!CAPI.CertAddCertificateLinkToStore(safeCertStoreHandle, x509.CertContext, CAPI.CERT_STORE_ADD_ALWAYS, SafeCertContextHandle.InvalidHandle)) throw new CryptographicException(Marshal.GetLastWin32Error()); } return safeCertStoreHandle; } internal static uint OidToAlgId (string value) { SafeLocalAllocHandle pszOid = StringToAnsiPtr(value); CAPI.CRYPT_OID_INFO pOIDInfo = CAPI.CryptFindOIDInfo(CAPI.CRYPT_OID_INFO_OID_KEY, pszOid, 0); return pOIDInfo.Algid; } internal static string FindOidInfo(uint keyType, string keyValue, OidGroup oidGroup) { Debug.Assert(OidGroup.AllGroups <= oidGroup && oidGroup <= OidGroup.Template, "Invalid OID group"); if (keyValue == null) throw new ArgumentNullException("keyValue"); if (keyValue.Length == 0) return null; SafeLocalAllocHandle pvKey = SafeLocalAllocHandle.InvalidHandle; switch(keyType) { case CAPI.CRYPT_OID_INFO_OID_KEY: pvKey = StringToAnsiPtr(keyValue); break; case CAPI.CRYPT_OID_INFO_NAME_KEY: pvKey = StringToUniPtr(keyValue); break; default: Debug.Assert(false); break; } CAPI.CRYPT_OID_INFO pOidInfo = CAPI.CryptFindOIDInfo(keyType, pvKey, oidGroup); // if we couldn't find the OID within a specific group, retry with the generic group if(pOidInfo.pszOID == null && oidGroup != OidGroup.AllGroups) pOidInfo = CAPI.CryptFindOIDInfo(keyType, pvKey, OidGroup.AllGroups); if (keyType == CAPI.CRYPT_OID_INFO_OID_KEY) return pOidInfo.pwszName; else return pOidInfo.pszOID; } // // verify the passed keyValue is valid as per X.208 // // The first number must be 0, 1 or 2. // Enforce all characters are digits and dots. // Enforce that no dot starts or ends the Oid, and disallow double dots. // Enforce there is at least one dot separator. // internal static void ValidateOidValue (string keyValue) { if (keyValue == null) throw new ArgumentNullException("keyValue"); int len = keyValue.Length; if (len < 2) goto error; // should not start with a dot. The first digit must be 0, 1 or 2. char c = keyValue[0]; if (c != '0' && c != '1' && c != '2') goto error; if (keyValue[1] != '.' || keyValue[len - 1] == '.') // should not end in a dot goto error; bool hasAtLeastOneDot = false; for (int i = 1; i < len; i++) { // ensure every character is either a digit or a dot if (Char.IsDigit(keyValue[i])) continue; if (keyValue[i] != '.' || keyValue[i + 1] == '.') // disallow double dots goto error; hasAtLeastOneDot = true; } if (hasAtLeastOneDot) return; error: throw new ArgumentException(SR.GetString(SR.Argument_InvalidOidValue)); } internal static SafeLocalAllocHandle CopyOidsToUnmanagedMemory (OidCollection oids) { SafeLocalAllocHandle safeLocalAllocHandle = SafeLocalAllocHandle.InvalidHandle; if (oids == null || oids.Count == 0) return safeLocalAllocHandle; int ptrSize = oids.Count * Marshal.SizeOf(typeof(IntPtr)); int oidSize = 0; foreach (Oid oid in oids) { oidSize += (oid.Value.Length + 1); } safeLocalAllocHandle = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr((uint) ptrSize + (uint) oidSize)); IntPtr pOid = new IntPtr((long)safeLocalAllocHandle.DangerousGetHandle() + ptrSize); for (int index=0; index < oids.Count; index++) { Marshal.WriteIntPtr(new IntPtr((long) safeLocalAllocHandle.DangerousGetHandle() + index * Marshal.SizeOf(typeof(IntPtr))), pOid); byte[] ansiOid = Encoding.ASCII.GetBytes(oids[index].Value); Marshal.Copy(ansiOid, 0, pOid, ansiOid.Length); pOid = new IntPtr((long) pOid + oids[index].Value.Length + 1); } return safeLocalAllocHandle; } internal static X509Certificate2Collection GetCertificates(SafeCertStoreHandle safeCertStoreHandle) { X509Certificate2Collection collection = new X509Certificate2Collection(); IntPtr pEnumContext = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, IntPtr.Zero); while (pEnumContext != IntPtr.Zero) { X509Certificate2 certificate = new X509Certificate2(pEnumContext); collection.Add(certificate); pEnumContext = CAPI.CertEnumCertificatesInStore(safeCertStoreHandle, pEnumContext); } return collection; } // // Verifies whether a certificate is valid for the specified policy. // S_OK means the certificate is valid for the specified policy. // S_FALSE means the certificate is invalid for the specified policy. // Anything else is an error. // internal static unsafe int VerifyCertificate (SafeCertContextHandle pCertContext, OidCollection applicationPolicy, OidCollection certificatePolicy, X509RevocationMode revocationMode, X509RevocationFlag revocationFlag, DateTime verificationTime, TimeSpan timeout, X509Certificate2Collection extraStore, IntPtr pszPolicy, IntPtr pdwErrorStatus) { if (pCertContext == null || pCertContext.IsInvalid) throw new ArgumentException("pCertContext"); CAPI.CERT_CHAIN_POLICY_PARA PolicyPara = new CAPI.CERT_CHAIN_POLICY_PARA(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_PARA))); CAPI.CERT_CHAIN_POLICY_STATUS PolicyStatus = new CAPI.CERT_CHAIN_POLICY_STATUS(Marshal.SizeOf(typeof(CAPI.CERT_CHAIN_POLICY_STATUS))); // Build the chain. SafeCertChainHandle pChainContext = SafeCertChainHandle.InvalidHandle; int hr = X509Chain.BuildChain(new IntPtr(CAPI.HCCE_CURRENT_USER), pCertContext, extraStore, applicationPolicy, certificatePolicy, revocationMode, revocationFlag, verificationTime, timeout, ref pChainContext); if (hr != CAPI.S_OK) return hr; // Verify the chain using the specified policy. if (CAPI.CertVerifyCertificateChainPolicy(pszPolicy, pChainContext, ref PolicyPara, ref PolicyStatus)) { if (pdwErrorStatus != IntPtr.Zero) *(uint*) pdwErrorStatus = PolicyStatus.dwError; if (PolicyStatus.dwError != 0) return CAPI.S_FALSE; } else { // The API failed. return Marshal.GetHRForLastWin32Error(); } return CAPI.S_OK; } internal static string GetSystemErrorString (int hr) { StringBuilder strMessage = new StringBuilder(512); uint dwErrorCode = CAPI.FormatMessage (CAPI.FORMAT_MESSAGE_FROM_SYSTEM | CAPI.FORMAT_MESSAGE_IGNORE_INSERTS, IntPtr.Zero, (uint) hr, CAPI.GetUserDefaultLCID(), strMessage, 511, IntPtr.Zero); if (dwErrorCode != 0) return strMessage.ToString(); else return SR.GetString(SR.Unknown_Error); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ListView.cs
- XmlCustomFormatter.cs
- SqlMethodCallConverter.cs
- PaintEvent.cs
- JournalEntryStack.cs
- InheritedPropertyChangedEventArgs.cs
- WindowsStartMenu.cs
- HtmlControl.cs
- ConfigurationHelpers.cs
- SoapAttributes.cs
- XmlArrayItemAttribute.cs
- RuleSet.cs
- MailBnfHelper.cs
- DecoderNLS.cs
- SQLSingleStorage.cs
- XDeferredAxisSource.cs
- CoreSwitches.cs
- SystemResourceKey.cs
- XmlNodeList.cs
- HostSecurityManager.cs
- DoubleCollectionConverter.cs
- TextSelectionProcessor.cs
- OdbcParameterCollection.cs
- ImageCodecInfoPrivate.cs
- WebServiceData.cs
- ApplicationGesture.cs
- RegexRunner.cs
- RotateTransform3D.cs
- MessageOperationFormatter.cs
- UnsafeNativeMethods.cs
- XPathNavigatorKeyComparer.cs
- DoubleAnimationClockResource.cs
- KeyValueConfigurationCollection.cs
- MarginCollapsingState.cs
- CheckBoxBaseAdapter.cs
- Site.cs
- BasicViewGenerator.cs
- DynamicMethod.cs
- EntityClassGenerator.cs
- PathGeometry.cs
- XmlnsDefinitionAttribute.cs
- ClosableStream.cs
- RepeaterItemEventArgs.cs
- xsdvalidator.cs
- PreDigestedSignedInfo.cs
- _ConnectionGroup.cs
- TextFormatter.cs
- QuaternionAnimation.cs
- MethodExecutor.cs
- Label.cs
- ResourceDisplayNameAttribute.cs
- BoundPropertyEntry.cs
- SafeRightsManagementQueryHandle.cs
- PowerModeChangedEventArgs.cs
- HandlerBase.cs
- NavigationProperty.cs
- DataSet.cs
- UInt16.cs
- OleDbParameterCollection.cs
- XmlDownloadManager.cs
- Internal.cs
- Renderer.cs
- ToolStripContentPanel.cs
- MetafileHeaderWmf.cs
- RemoteArgument.cs
- ContentDesigner.cs
- PropertyMetadata.cs
- Baml2006ReaderFrame.cs
- XmlConverter.cs
- EventKeyword.cs
- OleDbWrapper.cs
- DbMetaDataColumnNames.cs
- ClientTargetCollection.cs
- ConfigXmlElement.cs
- NextPreviousPagerField.cs
- ResourceSetExpression.cs
- SystemDiagnosticsSection.cs
- GridViewSelectEventArgs.cs
- mediaclock.cs
- SecurityTokenAttachmentMode.cs
- ReadOnlyCollection.cs
- DesignerOptionService.cs
- ModuleConfigurationInfo.cs
- CardSpaceShim.cs
- HtmlInputControl.cs
- WebPartDeleteVerb.cs
- XamlSerializer.cs
- Table.cs
- IMembershipProvider.cs
- IdentitySection.cs
- HttpCapabilitiesBase.cs
- FileStream.cs
- BounceEase.cs
- TreeNodeEventArgs.cs
- Adorner.cs
- MDIClient.cs
- PageAdapter.cs
- CodeDOMProvider.cs
- SelectionChangedEventArgs.cs
- TextEncodedRawTextWriter.cs