Ejemplo n.º 1
0
        /// <summary>
        /// Encodes a CERT_INFO.
        /// </summary>
        public static void Encode_CERT_INFO(CERT_INFO info, out IntPtr pEncoded, out int encodedSize)
        {
            pEncoded    = IntPtr.Zero;
            encodedSize = 0;

            IntPtr pData      = IntPtr.Zero;
            int    dwDataSize = 0;

            GCHandle hData = GCHandle.Alloc(info);

            try {
                // calculate amount of memory required.
                int bResult = Win32.CryptEncodeObjectEx(
                    Win32.X509_ASN_ENCODING,
                    (IntPtr)Win32.X509_CERT_CRL_TO_BE_SIGNED,
                    hData.AddrOfPinnedObject(),
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref dwDataSize);

                if (bResult == 0)
                {
                    throw GetLastError(StatusCodes.BadEncodingError, "Could not get size for CRL_INFO.");
                }

                // allocate memory.
                pData = Marshal.AllocHGlobal(dwDataSize);

                // decode blob.
                bResult = Win32.CryptEncodeObjectEx(
                    Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
                    (IntPtr)Win32.X509_CERT_CRL_TO_BE_SIGNED,
                    hData.AddrOfPinnedObject(),
                    0,
                    IntPtr.Zero,
                    pData,
                    ref dwDataSize);

                if (bResult == 0)
                {
                    throw GetLastError(StatusCodes.BadEncodingError, "Could not encoder CRL_INFO.");
                }

                // return results.
                pEncoded    = pData;
                encodedSize = dwDataSize;
                pData       = IntPtr.Zero;
            } finally {
                if (hData.IsAllocated)
                {
                    hData.Free();
                }

                if (pData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pData);
                }
            }
        }
Ejemplo n.º 2
0
        private static SafeCertContextHandle GetSignerInPKCS7Store(SafeCertStoreHandle hCertStore, SafeCryptMsgHandle hCryptMsg)
        {
            // make sure that there is at least one signer of the certificate store
            int dwSigners;
            int cbSigners = sizeof(int);

            if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_COUNT_PARAM, 0, out dwSigners, ref cbSigners))
            {
                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
            }
            ;
            if (dwSigners == 0)
            {
                throw ErrorCode.CRYPT_E_SIGNER_NOT_FOUND.ToCryptographicException();
            }

            // get the first signer from the store, and use that as the loaded certificate
            int cbData = 0;

            if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_INFO_PARAM, 0, null, ref cbData))
            {
                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
            }
            ;

            byte[] cmsgSignerBytes = new byte[cbData];
            if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_INFO_PARAM, 0, cmsgSignerBytes, ref cbData))
            {
                throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
            }
            ;

            CERT_INFO certInfo = default(CERT_INFO);

            unsafe
            {
                fixed(byte *pCmsgSignerBytes = cmsgSignerBytes)
                {
                    CMSG_SIGNER_INFO_Partial *pCmsgSignerInfo = (CMSG_SIGNER_INFO_Partial *)pCmsgSignerBytes;

                    certInfo.Issuer.cbData       = pCmsgSignerInfo->Issuer.cbData;
                    certInfo.Issuer.pbData       = pCmsgSignerInfo->Issuer.pbData;
                    certInfo.SerialNumber.cbData = pCmsgSignerInfo->SerialNumber.cbData;
                    certInfo.SerialNumber.pbData = pCmsgSignerInfo->SerialNumber.pbData;
                }

                SafeCertContextHandle pCertContext = null;

                if (!Interop.crypt32.CertFindCertificateInStore(hCertStore, CertFindType.CERT_FIND_SUBJECT_CERT, &certInfo, ref pCertContext))
                {
                    throw Marshal.GetHRForLastWin32Error().ToCryptographicException();
                }
                ;

                return(pCertContext);
            }
        }
Ejemplo n.º 3
0
        internal static CERT_EXTENSION FindExtension(SafeCertContextHandle certificateContext, string extensionOid)
        {
            Debug.Assert(certificateContext != null, "certificateContext != null");
            Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid, "!certificateContext.IsClosed && !certificateContext.IsInvalid");
            Debug.Assert(!String.IsNullOrEmpty(extensionOid), "!String.IsNullOrEmpty(extensionOid)");
            Debug.Assert(HasExtension(certificateContext, extensionOid), "HasExtension(extensionOid)");

            CERT_INFO certInfo  = GetCertInfo(certificateContext);
            IntPtr    extension = UnsafeNativeMethods.CertFindExtension(extensionOid,
                                                                        certInfo.cExtension,
                                                                        certInfo.rgExtension);

            return((CERT_EXTENSION)Marshal.PtrToStructure(extension, typeof(CERT_EXTENSION)));
        }
Ejemplo n.º 4
0
        internal static bool HasExtension(SafeCertContextHandle certificateContext, string extensionOid)
        {
            Debug.Assert(certificateContext != null, "certificateContext != null");
            Debug.Assert(!certificateContext.IsClosed && !certificateContext.IsInvalid, "!certificateContext.IsClosed && !certificateContext.IsInvalid");
            Debug.Assert(!String.IsNullOrEmpty(extensionOid), "!String.IsNullOrEmpty(extensionOid)");

            CERT_INFO certInfo = GetCertInfo(certificateContext);

            if (certInfo.cExtension == 0)
            {
                return(false);
            }

            return(UnsafeNativeMethods.CertFindExtension(extensionOid, certInfo.cExtension, certInfo.rgExtension) != IntPtr.Zero);
        }
Ejemplo n.º 5
0
        public unsafe X509Certificate2 GenerateCertificate(X509Certificate2 issuingCertificate, PrivateKey privateKey, X500DistinguishedName dn, string[] dnsNames, IPAddress[] ipAddresses = null, HashAlgorithm?signatureAlgorithm = null, DateTime?notBefore = null, DateTime?notAfter = null)
        {
            if (!issuingCertificate.HasPrivateKey)
            {
                throw new ArgumentException("Issuing certificate must have a private key.", nameof(issuingCertificate));
            }
            IntPtr basicEncodedDataPtr = IntPtr.Zero, certExtensionPtr = IntPtr.Zero;
            var    serialNumber = new byte[16];
            var    rng = RandomNumberGenerator.Create();

            rng.GetNonZeroBytes(serialNumber);
            serialNumber[15] &= 0x7F;
            fixed(byte *dnPtr = dn.RawData, issuerDnPtr = issuingCertificate.SubjectName.RawData, serialNumberPtr = serialNumber)
            {
                try
                {
                    var blob = new NATIVE_CRYPTOAPI_BLOB
                    {
                        cbData = (uint)dn.RawData.Length,
                        pbData = dnPtr
                    };
                    var signingSignatureAlgorithmIdentifier = new CRYPT_ALGORITHM_IDENTIFIER
                    {
                        pszObjId = issuingCertificate.SignatureAlgorithm.Value
                    };
                    using (var signingKey = ExtractKey(issuingCertificate))
                    {
                        var signingAlgorithmIdentifier = new CRYPT_ALGORITHM_IDENTIFIER
                        {
                            pszObjId = signatureAlgorithm != null?HashAlgorithmToSignatureAlgorithm(signingKey, signatureAlgorithm.Value) : issuingCertificate.SignatureAlgorithm.Value
                        };
                        using (PublicKeyInfo publicKey = privateKey.ToPublicKey(), signingPublicKey = signingKey.ToPublicKey())
                        {
                            using (var extensions = new MarshalX509ExtensionCollection())
                            {
                                using (extensions.Freeze())
                                {
                                    var usage = X509KeyUsageFlags.DigitalSignature;
                                    if (privateKey.AlgorithmGroup == AlgorithmGroup.RSA)
                                    {
                                        //Key encipherment is not valid for DSA/ECDSA
                                        usage |= X509KeyUsageFlags.KeyEncipherment;
                                    }
                                    extensions.Add(new X509BasicConstraintsExtension(false, false, 0, true));
                                    extensions.Add(new X509KeyUsageExtension(usage, true));
                                    extensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection {
                                        new Oid(OIDs.EKU_SERVER)
                                    }, false));
                                    extensions.Add(new X509SubjectAlternativeNameExtension(DnsAltNamesFromArray(dnsNames, ipAddresses ?? new IPAddress[0]), false));
                                    using (var sha1 = new SHA1CryptoServiceProvider())
                                    {
                                        var issuingKeyId = sha1.ComputeHash(signingPublicKey.Key);
                                        extensions.Add(new X509SubjectKeyIdentifierExtension(sha1.ComputeHash(publicKey.Key), false));
                                        extensions.Add(new X509AuthorityKeyIdentifierExtension(issuingKeyId, null));
                                    }
                                }
                                var certInfo = new CERT_INFO();
                                certInfo.Subject      = blob;
                                certInfo.SerialNumber = new NATIVE_CRYPTOAPI_BLOB {
                                    cbData = (uint)serialNumber.Length, pbData = serialNumberPtr
                                };
                                certInfo.SubjectPublicKeyInfo = publicKey.PublicKey;
                                certInfo.dwVersion            = CertificateVersion.CERT_V3;
                                certInfo.Issuer = new NATIVE_CRYPTOAPI_BLOB {
                                    cbData = (uint)issuingCertificate.SubjectName.RawData.Length, pbData = issuerDnPtr
                                };
                                certInfo.SignatureAlgorithm = signingAlgorithmIdentifier;
                                certInfo.NotAfter           = FileTimeHelper.ToFileTimeStructureUtc(notAfter ?? DateTime.Now.AddHours(-1).AddYears(5));
                                certInfo.NotBefore          = FileTimeHelper.ToFileTimeStructureUtc(notBefore ?? DateTime.Now.AddHours(-1));
                                certInfo.cExtension         = extensions.Extensions.cExtension;
                                certInfo.rgExtension        = extensions.Extensions.rgExtension;
                                var size           = 0u;
                                var CERT_INFO_TYPE = (IntPtr)2;
                                if (!Crypt32.CryptSignAndEncodeCertificate(signingKey.Handle, signingKey.KeySpec, EncodingType.X509_ASN_ENCODING, CERT_INFO_TYPE, ref certInfo, ref signingSignatureAlgorithmIdentifier, IntPtr.Zero, IntPtr.Zero, ref size))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                var buffer = Marshal.AllocHGlobal((int)size);
                                if (!Crypt32.CryptSignAndEncodeCertificate(signingKey.Handle, signingKey.KeySpec, EncodingType.X509_ASN_ENCODING, CERT_INFO_TYPE, ref certInfo, ref signingSignatureAlgorithmIdentifier, IntPtr.Zero, buffer, ref size))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                const int CERT_KEY_PROV_INFO_PROP_ID = 2;
                                var       certificate = new X509Certificate2(SerializeCertificate(buffer, size));
                                var       keyProvInfo = new CRYPT_KEY_PROV_INFO
                                {
                                    cProvParam        = 0,
                                    dwKeySpec         = privateKey.KeySpec,
                                    dwProvType        = privateKey.Handle.IsNCryptKey ? ProviderType.CNG : ProviderType.PROV_RSA_AES,
                                    pwszProvName      = privateKey.ProviderName,
                                    dwFlags           = 0,
                                    pwszContainerName = privateKey.Name
                                };
                                if (!Crypt32.CertSetCertificateContextProperty(certificate.Handle, CERT_KEY_PROV_INFO_PROP_ID, 0u, ref keyProvInfo))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                return(new X509Certificate2(certificate));
                            }
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(basicEncodedDataPtr);
                    Marshal.FreeHGlobal(certExtensionPtr);
                }
            }
        }
Ejemplo n.º 6
0
            //
            // 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;
            }
Ejemplo n.º 7
-1
        /// <summary>
        /// Encodes a CERT_INFO.
        /// </summary>
        public static void Encode_CERT_INFO(CERT_INFO info, out IntPtr pEncoded, out int encodedSize)
        {
            pEncoded = IntPtr.Zero;
            encodedSize = 0;

            IntPtr pData = IntPtr.Zero;
            int dwDataSize = 0;

            GCHandle hData = GCHandle.Alloc(info);

            try
            {
                // calculate amount of memory required.
                int bResult = Win32.CryptEncodeObjectEx(
                    Win32.X509_ASN_ENCODING,
                    (IntPtr)Win32.X509_CERT_CRL_TO_BE_SIGNED,
                    hData.AddrOfPinnedObject(),
                    0,
                    IntPtr.Zero,
                    IntPtr.Zero,
                    ref dwDataSize);

                if (bResult == 0)
                {
                    throw GetLastError(StatusCodes.BadEncodingError, "Could not get size for CRL_INFO.");
                }

                // allocate memory.
                pData = Marshal.AllocHGlobal(dwDataSize);

                // decode blob.
                bResult = Win32.CryptEncodeObjectEx(
                    Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
                    (IntPtr)Win32.X509_CERT_CRL_TO_BE_SIGNED,
                    hData.AddrOfPinnedObject(),
                    0,
                    IntPtr.Zero,
                    pData,
                    ref dwDataSize);

                if (bResult == 0)
                {
                    throw GetLastError(StatusCodes.BadEncodingError, "Could not encoder CRL_INFO.");
                }

                // return results.
                pEncoded = pData;
                encodedSize = dwDataSize;
                pData = IntPtr.Zero;
            }
            finally
            {
                if (hData.IsAllocated)
                {
                    hData.Free();
                }

                if (pData != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(pData);
                }
            }
        }