// // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb". // private static unsafe CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *EncodeKeyTransRecipientInfo(CmsRecipient recipient, HeapBlockRetainer hb) { // "recipient" is a deep-cloned CmsRecipient object whose lifetime this class controls. Because of this, we can pull out the CERT_CONTEXT* and CERT_INFO* pointers // and embed pointers to them in the memory block we return. Yes, this code is scary. // // (The use of SafeCertContextHandle here is about using a consistent pattern to get the CERT_CONTEXT (rather than the ugly (CERT_CONTEXT*)(recipient.Certificate.Handle) pattern.) // It's not about keeping the context alive.) using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle()) { CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext(); CERT_INFO * pCertInfo = pCertContext->pCertInfo; CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *pEncodeInfo = (CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO))); pEncodeInfo->cbSize = sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO); CRYPT_ALGORITHM_IDENTIFIER algId = pCertInfo->SubjectPublicKeyInfo.Algorithm; pEncodeInfo->KeyEncryptionAlgorithm = algId; pEncodeInfo->pvKeyEncryptionAuxInfo = IntPtr.Zero; pEncodeInfo->hCryptProv = IntPtr.Zero; pEncodeInfo->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey; pEncodeInfo->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb); return(pEncodeInfo); } }
public static void TestHandle() { // // Ensure that the Handle property returns a valid CER_CONTEXT pointer. // using (X509Certificate2 c = new X509Certificate2(TestData.MsCertificate)) { IntPtr h = c.Handle; unsafe { CERT_CONTEXT *pCertContext = (CERT_CONTEXT *)h; // Does the blob data match? int cbCertEncoded = pCertContext->cbCertEncoded; Assert.Equal(TestData.MsCertificate.Length, cbCertEncoded); byte[] pCertEncoded = new byte[cbCertEncoded]; Marshal.Copy((IntPtr)(pCertContext->pbCertEncoded), pCertEncoded, 0, cbCertEncoded); Assert.Equal(TestData.MsCertificate, pCertEncoded); // Does the serial number match? CERT_INFO *pCertInfo = pCertContext->pCertInfo; byte[] serialNumber = pCertInfo->SerialNumber.ToByteArray(); byte[] expectedSerial = "b00000000100dd9f3bd08b0aaf11b000000033".HexToByteArray(); Assert.Equal(expectedSerial, serialNumber); } } }
public unsafe void FindByExtension(string oidValue) { FindCore( delegate(SafeCertContextHandle pCertContext) { CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo; CERT_EXTENSION *pCertExtension = Interop.crypt32.CertFindExtension(oidValue, pCertInfo->cExtension, pCertInfo->rgExtension); GC.KeepAlive(pCertContext); return(pCertExtension != null); }); }
public unsafe void FindByKeyUsage(X509KeyUsageFlags keyUsage) { FindCore( delegate(SafeCertContextHandle pCertContext) { CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo; X509KeyUsageFlags actual; if (!Interop.crypt32.CertGetIntendedKeyUsage(CertEncodingType.All, pCertInfo, out actual, sizeof(X509KeyUsageFlags))) { return(true); // no key usage means it is valid for all key usages. } GC.KeepAlive(pCertContext); return((actual & keyUsage) == keyUsage); }); }
public unsafe void FindByCertificatePolicy(string oidValue) { FindCore( delegate(SafeCertContextHandle pCertContext) { CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo; CERT_EXTENSION *pCertExtension = Interop.crypt32.CertFindExtension(Oids.CertPolicies, pCertInfo->cExtension, pCertInfo->rgExtension); if (pCertExtension == null) { return(false); } bool foundMatch = false; byte[] extensionRawData = pCertExtension->Value.ToByteArray(); if (!extensionRawData.DecodeObjectNoThrow( CryptDecodeObjectStructType.X509_CERT_POLICIES, delegate(void *pvDecoded, int cbDecoded) { Debug.Assert(cbDecoded >= sizeof(CERT_POLICIES_INFO)); CERT_POLICIES_INFO *pCertPoliciesInfo = (CERT_POLICIES_INFO *)pvDecoded; for (int i = 0; i < pCertPoliciesInfo->cPolicyInfo; i++) { CERT_POLICY_INFO *pCertPolicyInfo = &(pCertPoliciesInfo->rgPolicyInfo[i]); string actual = Marshal.PtrToStringAnsi(pCertPolicyInfo->pszPolicyIdentifier) !; if (oidValue.Equals(actual, StringComparison.OrdinalIgnoreCase)) { foundMatch = true; break; } } } )) { return(false); } GC.KeepAlive(pCertContext); return(foundMatch); }); }
internal static unsafe partial bool CertGetIntendedKeyUsage( CertEncodingType dwCertEncodingType, CERT_INFO *pCertInfo, out X509KeyUsageFlags pbKeyUsage, int cbKeyUsage);
private StorePal CreatedLinkedStoreWithFindResults(X509FindType findType, Object findValue, bool validOnly) { unsafe { switch (findType) { case X509FindType.FindByThumbprint: { byte[] thumbPrint = ConfirmedCast <String>(findValue).DecodeHexString(); fixed(byte *pThumbPrint = thumbPrint) { CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(thumbPrint.Length, pThumbPrint); return(FindCore(CertFindType.CERT_FIND_HASH, &blob, validOnly)); } } case X509FindType.FindBySubjectName: { String subjectName = ConfirmedCast <String>(findValue); fixed(char *pSubjectName = subjectName) { return(FindCore(CertFindType.CERT_FIND_SUBJECT_STR, pSubjectName, validOnly)); } } case X509FindType.FindBySubjectDistinguishedName: { String subjectDistinguishedName = ConfirmedCast <String>(findValue); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { String actual = GetCertNameInfo(pCertContext, CertNameType.CERT_NAME_RDN_TYPE, CertNameFlags.None); return subjectDistinguishedName.Equals(actual, StringComparison.OrdinalIgnoreCase); } )); } case X509FindType.FindByIssuerName: { String issuerName = ConfirmedCast <String>(findValue); fixed(char *pIssuerName = issuerName) { return(FindCore(CertFindType.CERT_FIND_ISSUER_STR, pIssuerName, validOnly)); } } case X509FindType.FindByIssuerDistinguishedName: { String issuerDistinguishedName = ConfirmedCast <String>(findValue); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { String actual = GetCertNameInfo(pCertContext, CertNameType.CERT_NAME_RDN_TYPE, CertNameFlags.CERT_NAME_ISSUER_FLAG); return issuerDistinguishedName.Equals(actual, StringComparison.OrdinalIgnoreCase); } )); } case X509FindType.FindBySerialNumber: { String decimalOrHexString = ConfirmedCast <String>(findValue); // FindBySerialNumber allows the input format to be either in hex or decimal. Since we can't know which one was intended, // it compares against both interpretations and treats a match of either as a successful find. byte[] hexBytes = decimalOrHexString.DecodeHexString(); Array.Reverse(hexBytes); // String is big-endian, BigInteger constructor requires little-endian. BigInteger expected1 = PositiveBigIntegerFromByteArray(hexBytes); BigInteger ten = new BigInteger(10); BigInteger expected2 = BigInteger.Zero; foreach (char c in decimalOrHexString) { if (c >= '0' && c <= '9') { expected2 = BigInteger.Multiply(expected2, ten); expected2 = BigInteger.Add(expected2, c - '0'); } } return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { byte[] actual = pCertContext.CertContext->pCertInfo->SerialNumber.ToByteArray(); BigInteger actualAsBigInteger = PositiveBigIntegerFromByteArray(actual); // Convert to BigInteger as the comparison must not fail due to spurious leading zeros GC.KeepAlive(pCertContext); return expected1.Equals(actualAsBigInteger) || expected2.Equals(actualAsBigInteger); } )); } case X509FindType.FindByTimeValid: { DateTime dateTime = ConfirmedCast <DateTime>(findValue); FILETIME fileTime = FILETIME.FromDateTime(dateTime); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { int comparison = Interop.crypt32.CertVerifyTimeValidity(ref fileTime, pCertContext.CertContext->pCertInfo); GC.KeepAlive(pCertContext); return comparison == 0; } )); } case X509FindType.FindByTimeNotYetValid: { DateTime dateTime = ConfirmedCast <DateTime>(findValue); FILETIME fileTime = FILETIME.FromDateTime(dateTime); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { int comparison = Interop.crypt32.CertVerifyTimeValidity(ref fileTime, pCertContext.CertContext->pCertInfo); GC.KeepAlive(pCertContext); return comparison == -1; } )); } case X509FindType.FindByTimeExpired: { DateTime dateTime = ConfirmedCast <DateTime>(findValue); FILETIME fileTime = FILETIME.FromDateTime(dateTime); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { int comparison = Interop.crypt32.CertVerifyTimeValidity(ref fileTime, pCertContext.CertContext->pCertInfo); GC.KeepAlive(pCertContext); return comparison == 1; } )); } case X509FindType.FindByTemplateName: { String expected = ConfirmedCast <String>(findValue); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { // The template name can have 2 different formats: V1 format (<= Win2K) is just a string // V2 format (XP only) can be a friendly name or an OID. // An example of Template Name can be "ClientAuth". bool foundMatch = false; CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo; { CERT_EXTENSION *pV1Template = Interop.crypt32.CertFindExtension(Oids.EnrollCertTypeExtension, pCertInfo->cExtension, pCertInfo->rgExtension); if (pV1Template != null) { byte[] extensionRawData = pV1Template->Value.ToByteArray(); if (!extensionRawData.DecodeObjectNoThrow( CryptDecodeObjectStructType.X509_UNICODE_ANY_STRING, delegate(void *pvDecoded) { CERT_NAME_VALUE *pNameValue = (CERT_NAME_VALUE *)pvDecoded; String actual = Marshal.PtrToStringUni(new IntPtr(pNameValue->Value.pbData)); if (expected.Equals(actual, StringComparison.OrdinalIgnoreCase)) { foundMatch = true; } })) { return false; } } } if (!foundMatch) { CERT_EXTENSION *pV2Template = Interop.crypt32.CertFindExtension(Oids.CertificateTemplate, pCertInfo->cExtension, pCertInfo->rgExtension); if (pV2Template != null) { byte[] extensionRawData = pV2Template->Value.ToByteArray(); if (!extensionRawData.DecodeObjectNoThrow( CryptDecodeObjectStructType.X509_CERTIFICATE_TEMPLATE, delegate(void *pvDecoded) { CERT_TEMPLATE_EXT *pTemplateExt = (CERT_TEMPLATE_EXT *)pvDecoded; String actual = Marshal.PtrToStringAnsi(pTemplateExt->pszObjId); String expectedOidValue = OidInfo.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_NAME_KEY, expected, OidGroup.Template, fallBackToAllGroups: true).OID; if (expectedOidValue == null) { expectedOidValue = expected; } if (expected.Equals(actual, StringComparison.OrdinalIgnoreCase)) { foundMatch = true; } })) { return false; } } } GC.KeepAlive(pCertContext); return foundMatch; })); } case X509FindType.FindByApplicationPolicy: { String expected = ConfirmedOidValue(findValue, OidGroup.Policy); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { int numOids; int cbData = 0; if (!Interop.crypt32.CertGetValidUsages(1, ref pCertContext, out numOids, null, ref cbData)) { return false; } // -1 means the certificate is good for all usages. if (numOids == -1) { return true; } fixed(byte *pOidsPointer = new byte[cbData]) { if (!Interop.crypt32.CertGetValidUsages(1, ref pCertContext, out numOids, pOidsPointer, ref cbData)) { return false; } IntPtr *pOids = (IntPtr *)pOidsPointer; for (int i = 0; i < numOids; i++) { String actual = Marshal.PtrToStringAnsi(pOids[i]); if (expected.Equals(actual, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } } )); } case X509FindType.FindByCertificatePolicy: { String expected = ConfirmedOidValue(findValue, OidGroup.Policy); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo; CERT_EXTENSION *pCertExtension = Interop.crypt32.CertFindExtension(Oids.CertPolicies, pCertInfo->cExtension, pCertInfo->rgExtension); if (pCertExtension == null) { return false; } bool foundMatch = false; byte[] extensionRawData = pCertExtension->Value.ToByteArray(); if (!extensionRawData.DecodeObjectNoThrow( CryptDecodeObjectStructType.X509_CERT_POLICIES, delegate(void *pvDecoded) { CERT_POLICIES_INFO *pCertPoliciesInfo = (CERT_POLICIES_INFO *)pvDecoded; for (int i = 0; i < pCertPoliciesInfo->cPolicyInfo; i++) { CERT_POLICY_INFO *pCertPolicyInfo = &(pCertPoliciesInfo->rgPolicyInfo[i]); String actual = Marshal.PtrToStringAnsi(pCertPolicyInfo->pszPolicyIdentifier); if (expected.Equals(actual, StringComparison.OrdinalIgnoreCase)) { foundMatch = true; break; } } } )) { return false; } GC.KeepAlive(pCertContext); return foundMatch; } )); } case X509FindType.FindByExtension: { String oidValue = ConfirmedOidValue(findValue, OidGroup.ExtensionOrAttribute); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo; CERT_EXTENSION *pCertExtension = Interop.crypt32.CertFindExtension(oidValue, pCertInfo->cExtension, pCertInfo->rgExtension); GC.KeepAlive(pCertContext); return pCertExtension != null; } )); } case X509FindType.FindByKeyUsage: { X509KeyUsageFlags expected = ConfirmedX509KeyUsage(findValue); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo; X509KeyUsageFlags actual; if (!Interop.crypt32.CertGetIntendedKeyUsage(CertEncodingType.All, pCertInfo, out actual, sizeof(X509KeyUsageFlags))) { return true; // no key usage means it is valid for all key usages. } GC.KeepAlive(pCertContext); return (actual & expected) == expected; } )); } case X509FindType.FindBySubjectKeyIdentifier: { byte[] expected = ConfirmedCast <String>(findValue).DecodeHexString(); return(FindCore(validOnly, delegate(SafeCertContextHandle pCertContext) { int cbData = 0; if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_IDENTIFIER_PROP_ID, null, ref cbData)) { return false; } byte[] actual = new byte[cbData]; if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_IDENTIFIER_PROP_ID, actual, ref cbData)) { return false; } return expected.ContentsEqual(actual); } )); } default: throw new CryptographicException(SR.Cryptography_X509_InvalidFindType); } } }
public static unsafe partial int CertVerifyTimeValidity(ref FILETIME pTimeToVerify, CERT_INFO *pCertInfo);
public static extern unsafe bool CertGetIntendedKeyUsage(CertEncodingType dwCertEncodingType, CERT_INFO *pCertInfo, out X509KeyUsageFlags pbKeyUsage, int cbKeyUsage);
public static extern unsafe int CertVerifyTimeValidity([In] ref FILETIME pTimeToVerify, [In] CERT_INFO *pCertInfo);
public static extern int WTHelperCertIsSelfSigned([NativeTypeName("DWORD")] uint dwEncoding, [NativeTypeName("CERT_INFO *")] CERT_INFO *pCert);
public unsafe void FindByTemplateName(string templateName) { FindCore( delegate(SafeCertContextHandle pCertContext) { // The template name can have 2 different formats: V1 format (<= Win2K) is just a string // V2 format (XP only) can be a friendly name or an OID. // An example of Template Name can be "ClientAuth". bool foundMatch = false; CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo; { CERT_EXTENSION *pV1Template = Interop.crypt32.CertFindExtension(Oids.EnrollCertTypeExtension, pCertInfo->cExtension, pCertInfo->rgExtension); if (pV1Template != null) { byte[] extensionRawData = pV1Template->Value.ToByteArray(); if (!extensionRawData.DecodeObjectNoThrow( CryptDecodeObjectStructType.X509_UNICODE_ANY_STRING, delegate(void *pvDecoded, int cbDecoded) { Debug.Assert(cbDecoded >= sizeof(CERT_NAME_VALUE)); CERT_NAME_VALUE *pNameValue = (CERT_NAME_VALUE *)pvDecoded; string?actual = Marshal.PtrToStringUni(new IntPtr(pNameValue->Value.pbData)); if (templateName.Equals(actual, StringComparison.OrdinalIgnoreCase)) { foundMatch = true; } })) { return(false); } } } if (!foundMatch) { CERT_EXTENSION *pV2Template = Interop.crypt32.CertFindExtension(Oids.CertificateTemplate, pCertInfo->cExtension, pCertInfo->rgExtension); if (pV2Template != null) { byte[] extensionRawData = pV2Template->Value.ToByteArray(); if (!extensionRawData.DecodeObjectNoThrow( CryptDecodeObjectStructType.X509_CERTIFICATE_TEMPLATE, delegate(void *pvDecoded, int cbDecoded) { Debug.Assert(cbDecoded >= sizeof(CERT_TEMPLATE_EXT)); CERT_TEMPLATE_EXT *pTemplateExt = (CERT_TEMPLATE_EXT *)pvDecoded; string?actual = Marshal.PtrToStringAnsi(pTemplateExt->pszObjId); string?expectedOidValue = Interop.Crypt32.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_NAME_KEY, templateName, OidGroup.Template, fallBackToAllGroups: true).OID; if (expectedOidValue == null) { expectedOidValue = templateName; } if (expectedOidValue.Equals(actual, StringComparison.OrdinalIgnoreCase)) { foundMatch = true; } })) { return(false); } } } GC.KeepAlive(pCertContext); return(foundMatch); }); }
// // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb". // private static unsafe CERT_ID EncodeRecipientId(CmsRecipient recipient, SafeCertContextHandle hCertContext, CERT_CONTEXT *pCertContext, CERT_INFO *pCertInfo, HeapBlockRetainer hb) { CERT_ID recipientId = default(CERT_ID); SubjectIdentifierType type = recipient.RecipientIdentifierType; switch (type) { case SubjectIdentifierType.IssuerAndSerialNumber: { recipientId.dwIdChoice = CertIdChoice.CERT_ID_ISSUER_SERIAL_NUMBER; recipientId.u.IssuerSerialNumber.Issuer = pCertInfo->Issuer; recipientId.u.IssuerSerialNumber.SerialNumber = pCertInfo->SerialNumber; break; } case SubjectIdentifierType.SubjectKeyIdentifier: { byte[] ski = hCertContext.GetSubjectKeyIdentifer(); IntPtr pSki = hb.AllocBytes(ski); recipientId.dwIdChoice = CertIdChoice.CERT_ID_KEY_IDENTIFIER; recipientId.u.KeyId.cbData = (uint)(ski.Length); recipientId.u.KeyId.pbData = pSki; break; } default: // The public contract for CmsRecipient guarantees that SubjectKeyIdentifier and IssuerAndSerialNumber are the only two possibilities. Debug.Fail($"Unexpected SubjectIdentifierType: {type}"); throw new NotSupportedException(SR.Format(SR.Cryptography_Cms_Invalid_Subject_Identifier_Type, type)); } return(recipientId); }
// // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb". // private static unsafe CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO *EncodeKeyAgreeRecipientInfo(CmsRecipient recipient, AlgorithmIdentifier contentEncryptionAlgorithm, HeapBlockRetainer hb) { // "recipient" is a deep-cloned CmsRecipient object whose lifetime this class controls. Because of this, we can pull out the CERT_CONTEXT* and CERT_INFO* pointers without // bringing in all the SafeCertContextHandle machinery, and embed pointers to them in the memory block we return. Yes, this code is scary. using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle()) { CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext(); CERT_INFO * pCertInfo = pCertContext->pCertInfo; CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO *pEncodeInfo = (CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO))); pEncodeInfo->cbSize = sizeof(CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO); pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.Esdh); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = 0; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = IntPtr.Zero; pEncodeInfo->pvKeyEncryptionAuxInfo = null; string oidValue; AlgId algId = contentEncryptionAlgorithm.Oid.Value.ToAlgId(); if (algId == AlgId.CALG_RC2) { oidValue = Oids.CmsRc2Wrap; } else { oidValue = Oids.Cms3DesWrap; } pEncodeInfo->KeyWrapAlgorithm.pszObjId = hb.AllocAsciiString(oidValue); pEncodeInfo->KeyWrapAlgorithm.Parameters.cbData = 0; pEncodeInfo->KeyWrapAlgorithm.Parameters.pbData = IntPtr.Zero; pEncodeInfo->pvKeyWrapAuxInfo = GenerateEncryptionAuxInfoIfNeeded(contentEncryptionAlgorithm, hb); pEncodeInfo->hCryptProv = IntPtr.Zero; pEncodeInfo->dwKeySpec = 0; pEncodeInfo->dwKeyChoice = CmsKeyAgreeKeyChoice.CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE; pEncodeInfo->pEphemeralAlgorithm = (CRYPT_ALGORITHM_IDENTIFIER *)(hb.Alloc(sizeof(CRYPT_ALGORITHM_IDENTIFIER))); *(pEncodeInfo->pEphemeralAlgorithm) = pCertInfo->SubjectPublicKeyInfo.Algorithm; pEncodeInfo->UserKeyingMaterial.cbData = 0; pEncodeInfo->UserKeyingMaterial.pbData = IntPtr.Zero; CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *pEncryptedKey = (CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO))); pEncryptedKey->cbSize = sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO); pEncryptedKey->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey; pEncryptedKey->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb); pEncryptedKey->Date = default(FILETIME); pEncryptedKey->pOtherAttr = null; CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO **ppEncryptedKey = (CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO **)(hb.Alloc(sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *))); ppEncryptedKey[0] = pEncryptedKey; pEncodeInfo->cRecipientEncryptedKeys = 1; pEncodeInfo->rgpRecipientEncryptedKeys = ppEncryptedKey; return(pEncodeInfo); } }
// // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb". // private static unsafe CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *EncodeKeyTransRecipientInfo(CmsRecipient recipient, HeapBlockRetainer hb) { // "recipient" is a deep-cloned CmsRecipient object whose lifetime this class controls. Because of this, we can pull out the CERT_CONTEXT* and CERT_INFO* pointers // and embed pointers to them in the memory block we return. Yes, this code is scary. // // (The use of SafeCertContextHandle here is about using a consistent pattern to get the CERT_CONTEXT (rather than the ugly (CERT_CONTEXT*)(recipient.Certificate.Handle) pattern.) // It's not about keeping the context alive.) using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle()) { CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext(); CERT_INFO * pCertInfo = pCertContext->pCertInfo; CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *pEncodeInfo = (CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO))); pEncodeInfo->cbSize = sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO); if (recipient.RSAEncryptionPadding is null) { CRYPT_ALGORITHM_IDENTIFIER algId = pCertInfo->SubjectPublicKeyInfo.Algorithm; pEncodeInfo->KeyEncryptionAlgorithm = algId; } else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.Pkcs1) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.Rsa); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaPkcsParameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaPkcsParameters); } else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.OaepSHA1) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.RsaOaep); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha1Parameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha1Parameters); } else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.OaepSHA256) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.RsaOaep); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha256Parameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha256Parameters); } else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.OaepSHA384) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.RsaOaep); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha384Parameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha384Parameters); } else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.OaepSHA512) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.RsaOaep); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha512Parameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha512Parameters); } else { throw ErrorCode.CRYPT_E_UNKNOWN_ALGO.ToCryptographicException(); } pEncodeInfo->pvKeyEncryptionAuxInfo = IntPtr.Zero; pEncodeInfo->hCryptProv = IntPtr.Zero; pEncodeInfo->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey; pEncodeInfo->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb); return(pEncodeInfo); } }
// // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb". // private static unsafe CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *EncodeKeyTransRecipientInfo(CmsRecipient recipient, HeapBlockRetainer hb) { // "recipient" is a deep-cloned CmsRecipient object whose lifetime this class controls. Because of this, we can pull out the CERT_CONTEXT* and CERT_INFO* pointers // and embed pointers to them in the memory block we return. Yes, this code is scary. // // (The use of SafeCertContextHandle here is about using a consistent pattern to get the CERT_CONTEXT (rather than the ugly (CERT_CONTEXT*)(recipient.Certificate.Handle) pattern.) // It's not about keeping the context alive.) using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle()) { CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext(); CERT_INFO * pCertInfo = pCertContext->pCertInfo; CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *pEncodeInfo = (CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO))); pEncodeInfo->cbSize = sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO); RSAEncryptionPadding padding = recipient.RSAEncryptionPadding; if (padding is null) { if (recipient.Certificate.GetKeyAlgorithm() == Oids.RsaOaep) { byte[] parameters = recipient.Certificate.GetKeyAlgorithmParameters(); if (parameters == null || parameters.Length == 0) { padding = RSAEncryptionPadding.OaepSHA1; } else if (!PkcsHelpers.TryGetRsaOaepEncryptionPadding(parameters, out padding, out _)) { throw ErrorCode.CRYPT_E_UNKNOWN_ALGO.ToCryptographicException(); } } else { // gost falls in here padding = RSAEncryptionPadding.Pkcs1; } } if (padding == RSAEncryptionPadding.Pkcs1) { // begin: gost switch (recipient.Certificate.GetKeyAlgorithm()) { case Oids.Gost3410: case Oids.Gost3410_2012_256: case Oids.Gost3410_2012_512: { // copy from cert info explicitly pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(recipient.Certificate.GetKeyAlgorithm()); // uint, копируем pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData; // копируем из памяти и записываем var pbDataBytes = new byte[pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData]; Marshal.Copy(pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData, pbDataBytes, 0, pbDataBytes.Length); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(pbDataBytes); break; } default: { // end: gost pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.Rsa); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaPkcsParameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaPkcsParameters); break; } } } else if (padding == RSAEncryptionPadding.OaepSHA1) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.RsaOaep); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha1Parameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha1Parameters); } else if (padding == RSAEncryptionPadding.OaepSHA256) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.RsaOaep); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha256Parameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha256Parameters); } else if (padding == RSAEncryptionPadding.OaepSHA384) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.RsaOaep); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha384Parameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha384Parameters); } else if (padding == RSAEncryptionPadding.OaepSHA512) { pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(Oids.RsaOaep); pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha512Parameters.Length; pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha512Parameters); } else { throw ErrorCode.CRYPT_E_UNKNOWN_ALGO.ToCryptographicException(); } pEncodeInfo->pvKeyEncryptionAuxInfo = IntPtr.Zero; pEncodeInfo->hCryptProv = IntPtr.Zero; pEncodeInfo->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey; pEncodeInfo->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb); return(pEncodeInfo); } }