internal AsnEncodedData(string oid, CAPIBase.CRYPTOAPI_BLOB encodedBlob) : this(oid, CAPI.BlobToByteArray(encodedBlob)) { }
internal AsnEncodedData (Oid oid, CAPI.CRYPTOAPI_BLOB encodedBlob) : this(oid, CAPI.BlobToByteArray(encodedBlob)) {}
internal unsafe SubjectIdentifier (CAPI.CRYPTOAPI_BLOB issuer, CAPI.CRYPTOAPI_BLOB serialNumber) { // If serial number is 0, then it is the special SKI encoding or NoSignature bool isSKIorHashOnly = true; byte * pb = (byte *) serialNumber.pbData; for (uint i = 0; i < serialNumber.cbData; i++) { if (*pb++ != (byte) 0) { isSKIorHashOnly = false; break; } } if (isSKIorHashOnly) { byte[] issuerBytes = new byte[issuer.cbData]; Marshal.Copy(issuer.pbData, issuerBytes, 0, issuerBytes.Length); X500DistinguishedName dummyName = new X500DistinguishedName(issuerBytes); if (String.Compare(CAPI.DummySignerCommonName, dummyName.Name, StringComparison.OrdinalIgnoreCase) == 0) { Reset(SubjectIdentifierType.NoSignature, null); return; } } if (isSKIorHashOnly) { // Decode disguised SKI in issuer field (See WinCrypt.h for more info). Note that some certificates may contain // an all-zero serial number but not be encoded with an szOID_KEYID_RDN. In order to allow use of signatures created // using these certificates, we will first try to find the szOID_KEYID_RDN, but if it does not exist, fall back to just // decoding the incoming issuer and serial number. m_type = SubjectIdentifierType.SubjectKeyIdentifier; m_value = String.Empty; uint cbCertNameInfo = 0; SafeLocalAllocHandle pbCertNameInfo = SafeLocalAllocHandle.InvalidHandle; if (CAPI.DecodeObject(new IntPtr(CAPI.X509_NAME), issuer.pbData, issuer.cbData, out pbCertNameInfo, out cbCertNameInfo)) { using (pbCertNameInfo) { checked { CAPI.CERT_NAME_INFO certNameInfo = (CAPI.CERT_NAME_INFO) Marshal.PtrToStructure(pbCertNameInfo.DangerousGetHandle(), typeof(CAPI.CERT_NAME_INFO)); for (uint i = 0; i < certNameInfo.cRDN; i++) { CAPI.CERT_RDN certRdn = (CAPI.CERT_RDN) Marshal.PtrToStructure(new IntPtr((long) certNameInfo.rgRDN + (long) (i * Marshal.SizeOf(typeof(CAPI.CERT_RDN)))), typeof(CAPI.CERT_RDN)); for (uint j = 0; j < certRdn.cRDNAttr; j++) { CAPI.CERT_RDN_ATTR certRdnAttr = (CAPI.CERT_RDN_ATTR)Marshal.PtrToStructure(new IntPtr((long)certRdn.rgRDNAttr + (long)(j * Marshal.SizeOf(typeof(CAPI.CERT_RDN_ATTR)))), typeof(CAPI.CERT_RDN_ATTR)); if (String.Compare(CAPI.szOID_KEYID_RDN, certRdnAttr.pszObjId, StringComparison.OrdinalIgnoreCase) == 0) { if (certRdnAttr.dwValueType == CAPI.CERT_RDN_OCTET_STRING) { byte[] ski = new byte[certRdnAttr.Value.cbData]; Marshal.Copy(certRdnAttr.Value.pbData, ski, 0, ski.Length); Reset(SubjectIdentifierType.SubjectKeyIdentifier, X509Utils.EncodeHexString(ski)); return; } } } } } } } } CAPI.CERT_ISSUER_SERIAL_NUMBER IssuerAndSerial; IssuerAndSerial.Issuer = issuer; IssuerAndSerial.SerialNumber = serialNumber; X509IssuerSerial issuerSerial = PkcsUtils.DecodeIssuerSerial(IssuerAndSerial); Reset(SubjectIdentifierType.IssuerAndSerialNumber, issuerSerial); }
internal CryptographicAttributeObjectCollection (CAPI.CRYPT_ATTRIBUTES cryptAttributes) { m_list = new ArrayList((int)cryptAttributes.cAttr); for (uint index = 0; index < cryptAttributes.cAttr; index++) { IntPtr pCryptAttribute = new IntPtr((long)cryptAttributes.rgAttr + (index * Marshal.SizeOf(typeof(CAPI.CRYPT_ATTRIBUTE)))); m_list.Add(new CryptographicAttributeObject(pCryptAttribute)); } }
internal AlgorithmIdentifier (CAPI.CERT_PUBLIC_KEY_INFO keyInfo) { SafeLocalAllocHandle pKeyInfo = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CERT_PUBLIC_KEY_INFO)))); Marshal.StructureToPtr(keyInfo, pKeyInfo.DangerousGetHandle(), false); int keyLength = (int) CAPI.CAPISafe.CertGetPublicKeyLength(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, pKeyInfo.DangerousGetHandle()); byte[] parameters = new byte[keyInfo.Algorithm.Parameters.cbData]; if (parameters.Length > 0) { Marshal.Copy(keyInfo.Algorithm.Parameters.pbData, parameters, 0, parameters.Length); } Marshal.DestroyStructure(pKeyInfo.DangerousGetHandle(), typeof(CAPI.CERT_PUBLIC_KEY_INFO)); pKeyInfo.Dispose(); Reset(Oid.FromOidValue(keyInfo.Algorithm.pszObjId, OidGroup.PublicKeyAlgorithm), keyLength, parameters); }
internal SubjectIdentifier (CAPI.CERT_INFO certInfo) : this(certInfo.Issuer, certInfo.SerialNumber) {}
internal unsafe static X509IssuerSerial DecodeIssuerSerial (CAPI.CERT_ISSUER_SERIAL_NUMBER pIssuerAndSerial) { SafeLocalAllocHandle ptr = SafeLocalAllocHandle.InvalidHandle; uint cbSize = CAPI.CAPISafe.CertNameToStrW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, new IntPtr(&pIssuerAndSerial.Issuer), CAPI.CERT_X500_NAME_STR | CAPI.CERT_NAME_STR_REVERSE_FLAG, ptr, 0); if (cbSize <= 1) // The API actually return 1 when It fails; which is not what the documentation says. throw new CryptographicException(Marshal.GetLastWin32Error()); ptr = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(checked(2 * cbSize))); cbSize = CAPI.CAPISafe.CertNameToStrW(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, new IntPtr(&pIssuerAndSerial.Issuer), CAPI.CERT_X500_NAME_STR | CAPI.CERT_NAME_STR_REVERSE_FLAG, ptr, cbSize); if (cbSize <= 1) throw new CryptographicException(Marshal.GetLastWin32Error()); X509IssuerSerial issuerSerial = new X509IssuerSerial(); issuerSerial.IssuerName = Marshal.PtrToStringUni(ptr.DangerousGetHandle()); byte[] serial = new byte[pIssuerAndSerial.SerialNumber.cbData]; Marshal.Copy(pIssuerAndSerial.SerialNumber.pbData, serial, 0, serial.Length); issuerSerial.SerialNumber = X509Utils.EncodeHexStringFromInt(serial); ptr.Dispose(); return issuerSerial; }
internal SubjectIdentifierOrKey (CAPI.CERT_ID certId) { switch (certId.dwIdChoice) { case CAPI.CERT_ID_ISSUER_SERIAL_NUMBER: X509IssuerSerial issuerSerial = PkcsUtils.DecodeIssuerSerial(certId.Value.IssuerSerialNumber); Reset(SubjectIdentifierOrKeyType.IssuerAndSerialNumber, issuerSerial); break; case CAPI.CERT_ID_KEY_IDENTIFIER: byte[] ski = new byte[certId.Value.KeyId.cbData]; Marshal.Copy(certId.Value.KeyId.pbData, ski, 0, ski.Length); Reset(SubjectIdentifierOrKeyType.SubjectKeyIdentifier, X509Utils.EncodeHexString(ski)); break; default: throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Invalid_Subject_Identifier_Type"), certId.dwIdChoice.ToString(CultureInfo.InvariantCulture)); } }
internal KeyAgreeRecipientInfo (SafeLocalAllocHandle pRecipientInfo, CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO publicKeyRecipient, uint index, uint subIndex) : base(RecipientInfoType.KeyAgreement, RecipientSubType.PublicKeyAgreement, pRecipientInfo, publicKeyRecipient, index) { checked { IntPtr pEncryptedKeyInfo = Marshal.ReadIntPtr(new IntPtr((long) publicKeyRecipient.rgpRecipientEncryptedKeys + (long) (subIndex * Marshal.SizeOf(typeof(IntPtr))))); CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_INFO encryptedKeyInfo = (CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_INFO) Marshal.PtrToStructure(pEncryptedKeyInfo, typeof(CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_INFO)); Reset(CAPI.CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY, publicKeyRecipient.dwVersion, encryptedKeyInfo, subIndex); } }
// // Private methods. // private void Reset (uint originatorChoice, uint version, CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_INFO encryptedKeyInfo, uint subIndex) { m_encryptedKeyInfo = encryptedKeyInfo; m_originatorChoice = originatorChoice; m_version = (int) version; m_originatorIdentifier = null; m_userKeyMaterial = new byte[0]; m_encryptionAlgorithm = null; m_recipientIdentifier = null; m_encryptedKey = new byte[0]; m_date = DateTime.MinValue; m_otherKeyAttribute = null; m_subIndex = subIndex; }
internal KeyTransRecipientInfo (SafeLocalAllocHandle pRecipientInfo, CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO keyTrans, uint index) : base(RecipientInfoType.KeyTransport, RecipientSubType.CmsKeyTransport, pRecipientInfo, keyTrans, index) { Reset((int) keyTrans.dwVersion); }
internal unsafe KeyTransRecipientInfo (SafeLocalAllocHandle pRecipientInfo, CAPI.CERT_INFO certInfo, uint index) : base(RecipientInfoType.KeyTransport, RecipientSubType.Pkcs7KeyTransport, pRecipientInfo, certInfo, index) { // If serial number is 0, then it is the special SKI encoding. int version = 2; byte * pb = (byte *) certInfo.SerialNumber.pbData; for (int i = 0; i < certInfo.SerialNumber.cbData; i++) { if (*pb++ != (byte) 0) { version = 0; break; } } Reset(version); }
internal AsnEncodedData(Oid oid, CAPI.CRYPTOAPI_BLOB encodedBlob) : this(oid, CAPI.BlobToByteArray(encodedBlob)) { }
// // Constructors. // internal X500DistinguishedName (CAPI.CRYPTOAPI_BLOB encodedDistinguishedNameBlob) : base (new Oid(), encodedDistinguishedNameBlob) {}
internal static AsnEncodedDataCollection GetAsnEncodedDataCollection (CAPI.CRYPT_ATTRIBUTE cryptAttribute) { AsnEncodedDataCollection list = new AsnEncodedDataCollection(); Oid oid = new Oid(cryptAttribute.pszObjId); string szOid = oid.Value; for (uint index = 0; index < cryptAttribute.cValue; index++) { checked { IntPtr pAttributeBlob = new IntPtr((long)cryptAttribute.rgValue + (index * Marshal.SizeOf(typeof(CAPI.CRYPTOAPI_BLOB)))); Pkcs9AttributeObject attribute = new Pkcs9AttributeObject(oid, CAPI.BlobToByteArray(pAttributeBlob)); Pkcs9AttributeObject customAttribute = CryptoConfig.CreateFromName(szOid) as Pkcs9AttributeObject; if (customAttribute != null) { customAttribute.CopyFrom(attribute); attribute = customAttribute; } list.Add(attribute); } } return list; }
internal PublicKeyInfo (CAPI.CERT_PUBLIC_KEY_INFO keyInfo) { m_algorithm = new AlgorithmIdentifier(keyInfo); m_keyValue = new byte[keyInfo.PublicKey.cbData]; if (m_keyValue.Length > 0) { Marshal.Copy(keyInfo.PublicKey.pbData, m_keyValue, 0, m_keyValue.Length); } }
internal static AsnEncodedDataCollection GetAsnEncodedDataCollection (CAPI.CRYPT_ATTRIBUTE_TYPE_VALUE cryptAttribute) { AsnEncodedDataCollection list = new AsnEncodedDataCollection(); list.Add(new Pkcs9AttributeObject(new Oid(cryptAttribute.pszObjId), CAPI.BlobToByteArray(cryptAttribute.Value))); return list; }
internal SubjectIdentifierOrKey (CAPI.CERT_PUBLIC_KEY_INFO publicKeyInfo) { Reset(SubjectIdentifierOrKeyType.PublicKeyInfo, new PublicKeyInfo(publicKeyInfo)); }
public static byte[] Unprotect(byte[] encryptedData, byte[] optionalEntropy, DataProtectionScope scope) { if (encryptedData == null) { throw new ArgumentNullException("encryptedData"); } if (Environment.OSVersion.Platform == PlatformID.Win32Windows) { throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); } GCHandle pbDataIn = new GCHandle(); GCHandle pOptionalEntropy = new GCHandle(); CAPI.CRYPTOAPI_BLOB userData = new CAPI.CRYPTOAPI_BLOB(); RuntimeHelpers.PrepareConstrainedRegions(); try { pbDataIn = GCHandle.Alloc(encryptedData, GCHandleType.Pinned); CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB(); dataIn.cbData = (uint)encryptedData.Length; dataIn.pbData = pbDataIn.AddrOfPinnedObject(); CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB(); if (optionalEntropy != null) { pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned); entropy.cbData = (uint)optionalEntropy.Length; entropy.pbData = pOptionalEntropy.AddrOfPinnedObject(); } uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN; if (scope == DataProtectionScope.LocalMachine) { dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE; } unsafe { if (!CAPI.CryptUnprotectData(new IntPtr(&dataIn), IntPtr.Zero, new IntPtr(&entropy), IntPtr.Zero, IntPtr.Zero, dwFlags, new IntPtr(&userData))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } // In some cases, the API would fail due to OOM but simply return a null pointer. if (userData.pbData == IntPtr.Zero) { throw new OutOfMemoryException(); } byte[] data = new byte[(int)userData.cbData]; Marshal.Copy(userData.pbData, data, 0, data.Length); return(data); } catch (EntryPointNotFoundException) { throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); } finally { if (pbDataIn.IsAllocated) { pbDataIn.Free(); } if (pOptionalEntropy.IsAllocated) { pOptionalEntropy.Free(); } if (userData.pbData != IntPtr.Zero) { CAPI.CAPISafe.ZeroMemory(userData.pbData, userData.cbData); CAPI.CAPISafe.LocalFree(userData.pbData); } } }
internal AlgorithmIdentifier (CAPI.CRYPT_ALGORITHM_IDENTIFIER algorithmIdentifier) { int keyLength = 0; uint cbParameters = 0; SafeLocalAllocHandle pbParameters = SafeLocalAllocHandle.InvalidHandle; byte[] parameters = new byte[0]; uint algId = X509Utils.OidToAlgId(algorithmIdentifier.pszObjId); if (algId == CAPI.CALG_RC2) { if (algorithmIdentifier.Parameters.cbData > 0) { if (!CAPI.DecodeObject(new IntPtr(CAPI.PKCS_RC2_CBC_PARAMETERS), algorithmIdentifier.Parameters.pbData, algorithmIdentifier.Parameters.cbData, out pbParameters, out cbParameters)) throw new CryptographicException(Marshal.GetLastWin32Error()); CAPI.CRYPT_RC2_CBC_PARAMETERS rc2Parameters = (CAPI.CRYPT_RC2_CBC_PARAMETERS) Marshal.PtrToStructure(pbParameters.DangerousGetHandle(), typeof(CAPI.CRYPT_RC2_CBC_PARAMETERS)); switch (rc2Parameters.dwVersion) { case CAPI.CRYPT_RC2_40BIT_VERSION: keyLength = 40; break; case CAPI.CRYPT_RC2_56BIT_VERSION: keyLength = 56; break; case CAPI.CRYPT_RC2_128BIT_VERSION: keyLength = 128; break; } // Retrieve IV if available. if (rc2Parameters.fIV) { parameters = (byte[]) rc2Parameters.rgbIV.Clone(); } } } else if (algId == CAPI.CALG_RC4 || algId == CAPI.CALG_DES || algId == CAPI.CALG_3DES) { // Retrieve the IV if available. For non RC2, the parameter contains the IV // (for RC4 the IV is really the salt). There are (128 - KeyLength) / 8 // bytes of RC4 salt. if (algorithmIdentifier.Parameters.cbData > 0) { if (!CAPI.DecodeObject(new IntPtr(CAPI.X509_OCTET_STRING), algorithmIdentifier.Parameters.pbData, algorithmIdentifier.Parameters.cbData, out pbParameters, out cbParameters)) throw new CryptographicException(Marshal.GetLastWin32Error()); if (cbParameters > 0) { if (algId == CAPI.CALG_RC4) { CAPI.CRYPTOAPI_BLOB saltBlob = (CAPI.CRYPTOAPI_BLOB) Marshal.PtrToStructure(pbParameters.DangerousGetHandle(), typeof(CAPI.CRYPTOAPI_BLOB)); if (saltBlob.cbData > 0) { parameters = new byte[saltBlob.cbData]; Marshal.Copy(saltBlob.pbData, parameters, 0, parameters.Length); } } else { parameters = new byte[cbParameters]; Marshal.Copy(pbParameters.DangerousGetHandle(), parameters, 0, parameters.Length); } } } // Determine key length. if (algId == CAPI.CALG_RC4) { // For RC4, keyLength = 128 - (salt length * 8). keyLength = 128 - ((int) parameters.Length * 8); } else if (algId == CAPI.CALG_DES) { // DES key length is fixed at 64 (or 56 without the parity bits). keyLength = 64; } else { // 3DES key length is fixed at 192 (or 168 without the parity bits). keyLength = 192; } } else { // Everything else, don't decode it as CAPI may not expose or know how. if (algorithmIdentifier.Parameters.cbData > 0) { parameters = new byte[algorithmIdentifier.Parameters.cbData]; Marshal.Copy(algorithmIdentifier.Parameters.pbData, parameters, 0, parameters.Length); } } Reset(Oid.FromOidValue(algorithmIdentifier.pszObjId, OidGroup.All), keyLength, parameters); pbParameters.Dispose(); }
public static byte[] Protect(byte[] userData, byte[] optionalEntropy, DataProtectionScope scope) { if (userData == null) { throw new ArgumentNullException("userData"); } if (Environment.OSVersion.Platform == PlatformID.Win32Windows) { throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); } GCHandle pbDataIn = new GCHandle(); GCHandle pOptionalEntropy = new GCHandle(); CAPI.CRYPTOAPI_BLOB blob = new CAPI.CRYPTOAPI_BLOB(); RuntimeHelpers.PrepareConstrainedRegions(); try { pbDataIn = GCHandle.Alloc(userData, GCHandleType.Pinned); CAPI.CRYPTOAPI_BLOB dataIn = new CAPI.CRYPTOAPI_BLOB(); dataIn.cbData = (uint)userData.Length; dataIn.pbData = pbDataIn.AddrOfPinnedObject(); CAPI.CRYPTOAPI_BLOB entropy = new CAPI.CRYPTOAPI_BLOB(); if (optionalEntropy != null) { pOptionalEntropy = GCHandle.Alloc(optionalEntropy, GCHandleType.Pinned); entropy.cbData = (uint)optionalEntropy.Length; entropy.pbData = pOptionalEntropy.AddrOfPinnedObject(); } uint dwFlags = CAPI.CRYPTPROTECT_UI_FORBIDDEN; if (scope == DataProtectionScope.LocalMachine) { dwFlags |= CAPI.CRYPTPROTECT_LOCAL_MACHINE; } unsafe { if (!CAPI.CryptProtectData(new IntPtr(&dataIn), String.Empty, new IntPtr(&entropy), IntPtr.Zero, IntPtr.Zero, dwFlags, new IntPtr(&blob))) { int lastWin32Error = Marshal.GetLastWin32Error(); // One of the most common reasons that DPAPI operations fail is that the user // profile is not loaded (for instance in the case of impersonation or running in a // service. In those cases, throw an exception that provides more specific details // about what happened. if (CAPI.ErrorMayBeCausedByUnloadedProfile(lastWin32Error)) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_DpApi_ProfileMayNotBeLoaded")); } else { throw new CryptographicException(lastWin32Error); } } } // In some cases, the API would fail due to OOM but simply return a null pointer. if (blob.pbData == IntPtr.Zero) { throw new OutOfMemoryException(); } byte[] encryptedData = new byte[(int)blob.cbData]; Marshal.Copy(blob.pbData, encryptedData, 0, encryptedData.Length); return(encryptedData); } catch (EntryPointNotFoundException) { throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_PlatformRequiresNT")); } finally { if (pbDataIn.IsAllocated) { pbDataIn.Free(); } if (pOptionalEntropy.IsAllocated) { pOptionalEntropy.Free(); } if (blob.pbData != IntPtr.Zero) { CAPI.CAPISafe.ZeroMemory(blob.pbData, blob.cbData); CAPI.CAPISafe.LocalFree(blob.pbData); } } }
internal SubjectIdentifier (CAPI.CMSG_SIGNER_INFO signerInfo) : this(signerInfo.Issuer, signerInfo.SerialNumber) {}
internal AsnEncodedData(System.Security.Cryptography.Oid oid, CAPIBase.CRYPTOAPI_BLOB encodedBlob) : this(oid, CAPI.BlobToByteArray(encodedBlob)) { }
byte[] BlobToByteArray(CAPI.CRYPTOAPI_BLOB blob) { if (blob.cbData == 0) return new byte[0]; byte[] data = new byte[blob.cbData]; Marshal.Copy(blob.pbData, data, 0, data.Length); return data; }
internal CryptographicAttributeObject (CAPI.CRYPT_ATTRIBUTE_TYPE_VALUE cryptAttribute) : this(new Oid(cryptAttribute.pszObjId), PkcsUtils.GetAsnEncodedDataCollection(cryptAttribute)) { }