예제 #1
0
        private static unsafe byte[] ToBigEndianByteArray(CapiNative.CRYPTOAPI_BLOB blob)
        {
            int count = blob.cbData;

            byte[] data = new byte[count];
            Marshal.Copy(blob.pbData, data, 0, count);
            Array.Reverse(data);
            return(data);
        }
        private static byte[] CalculateSignerPublicKeyToken(AsymmetricAlgorithm key)
        {
            Debug.Assert(key != null, "key != null");

            ICspAsymmetricAlgorithm cspAlgorithm = key as ICspAsymmetricAlgorithm;

            if (cspAlgorithm == null)
            {
                return(null);
            }

            byte[] publicKey = cspAlgorithm.ExportCspBlob(false);
            SafeAxlBufferHandle tokenBuffer;

            unsafe
            {
                fixed(byte *pPublicKey = publicKey)
                {
                    // Safe, since we're ensuring the CAPI buffer going in is sized correctly
                    CapiNative.CRYPTOAPI_BLOB keyBlob = new CapiNative.CRYPTOAPI_BLOB();
                    keyBlob.cbData = publicKey.Length;
                    keyBlob.pbData = new IntPtr(pPublicKey);

                    int hrToken = CapiNative.UnsafeNativeMethods._AxlPublicKeyBlobToPublicKeyToken(ref keyBlob,
                                                                                                   out tokenBuffer);

                    if (((uint)hrToken & 0x80000000) != 0)
                    {
                        return(null);
                    }
                }
            }

            bool acquired = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                tokenBuffer.DangerousAddRef(ref acquired);
                return(HexStringToBytes(Marshal.PtrToStringUni(tokenBuffer.DangerousGetHandle())));
            }
            finally {
                if (acquired)
                {
                    tokenBuffer.DangerousRelease();
                }
            }
        }
예제 #3
0
        private static unsafe byte[] CalculateSignerPublicKeyToken(AsymmetricAlgorithm key)
        {
            SafeAxlBufferHandle handle;

            byte[] buffer2;
            ICspAsymmetricAlgorithm algorithm = key as ICspAsymmetricAlgorithm;

            if (algorithm == null)
            {
                return(null);
            }
            byte[] buffer = algorithm.ExportCspBlob(false);
            fixed(byte *numRef = buffer)
            {
                CapiNative.CRYPTOAPI_BLOB pCspPublicKeyBlob = new CapiNative.CRYPTOAPI_BLOB {
                    cbData = buffer.Length,
                    pbData = new IntPtr((void *)numRef)
                };
                if ((CapiNative.UnsafeNativeMethods._AxlPublicKeyBlobToPublicKeyToken(ref pCspPublicKeyBlob, out handle) & -2147483648) != 0)
                {
                    return(null);
                }
            }

            bool success = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                handle.DangerousAddRef(ref success);
                buffer2 = HexStringToBytes(Marshal.PtrToStringUni(handle.DangerousGetHandle()));
            }
            finally
            {
                if (success)
                {
                    handle.DangerousRelease();
                }
            }
            return(buffer2);
        }
        private AuthenticodeSignatureInformation VerifyAuthenticodeSignature(XmlElement signatureNode,
                                                                             X509RevocationFlag revocationFlag,
                                                                             X509RevocationMode revocationMode)
        {
            Debug.Assert(signatureNode != null, "signatureNode != null");

            // See if there is an Authenticode signature on the manifest
            XmlElement licenseNode = signatureNode.SelectSingleNode("ds:KeyInfo/msrel:RelData/r:license",
                                                                    m_namespaceManager) as XmlElement;

            if (licenseNode == null)
            {
                return(null);
            }

            // Make sure that the signature is for this manifest
            SignatureVerificationResult identityVerification = VerifyAuthenticodeSignatureIdentity(licenseNode);

            if (identityVerification != SignatureVerificationResult.Valid)
            {
                return(new AuthenticodeSignatureInformation(identityVerification));
            }

            SignatureVerificationResult hashVerification = VerifyAuthenticodeExpectedHash(licenseNode);

            if (hashVerification != SignatureVerificationResult.Valid)
            {
                return(new AuthenticodeSignatureInformation(hashVerification));
            }

            // Verify the signature, extracting information about it
            AuthenticodeSignatureInformation authenticodeSignature = null;

            X509Native.AXL_AUTHENTICODE_SIGNER_INFO signer = new X509Native.AXL_AUTHENTICODE_SIGNER_INFO();
            signer.cbSize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_SIGNER_INFO));

            X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO timestamper = new X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO();
            timestamper.cbsize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO));

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                byte[] licenseXml = Encoding.UTF8.GetBytes(licenseNode.OuterXml);
                X509Native.AxlVerificationFlags verificationFlags = MapRevocationFlags(revocationFlag,
                                                                                       revocationMode);

                unsafe
                {
                    fixed(byte *pLicenseXml = licenseXml)
                    {
                        // Safe since we're verifying the size of this buffer is correct
                        CapiNative.CRYPTOAPI_BLOB xmlBlob = new CapiNative.CRYPTOAPI_BLOB();
                        xmlBlob.cbData = licenseXml.Length;
                        xmlBlob.pbData = new IntPtr(pLicenseXml);

                        int hrVerify = X509Native.UnsafeNativeMethods.CertVerifyAuthenticodeLicense(ref xmlBlob,
                                                                                                    verificationFlags,
                                                                                                    ref signer,
                                                                                                    ref timestamper);

                        if (hrVerify == (int)SignatureVerificationResult.MissingSignature)
                        {
                            return(new AuthenticodeSignatureInformation(SignatureVerificationResult.MissingSignature));
                        }
                    }
                }

                X509Chain signatureChain = BuildSignatureChain(signer,
                                                               licenseNode,
                                                               revocationFlag,
                                                               revocationMode);

                TimestampInformation timestamp = GetTimestampInformation(timestamper,
                                                                         licenseNode);

                authenticodeSignature = new AuthenticodeSignatureInformation(signer,
                                                                             signatureChain,
                                                                             timestamp);
            }
            finally {
                X509Native.UnsafeNativeMethods.CertFreeAuthenticodeSignerInfo(ref signer);
                X509Native.UnsafeNativeMethods.CertFreeAuthenticodeTimestamperInfo(ref timestamper);
            }

            // Verify the signing certificate matches the expected publisher
            Debug.Assert(authenticodeSignature != null, "authenticodeSignature != null");
            if (authenticodeSignature.SigningCertificate == null)
            {
                return(new AuthenticodeSignatureInformation(authenticodeSignature.VerificationResult));
            }

            SignatureVerificationResult publisherMatch = VerifyAuthenticodePublisher(authenticodeSignature.SigningCertificate);

            if (publisherMatch != SignatureVerificationResult.Valid)
            {
                return(new AuthenticodeSignatureInformation(publisherMatch));
            }

            return(authenticodeSignature);
        }
예제 #5
0
        internal static SafeCertificateContextHandle CreateSelfSignedCertificate(SafeNCryptKeyHandle key,
                                                                                 byte[] subjectName,
                                                                                 X509CertificateCreationOptions creationOptions,
                                                                                 string signatureAlgorithmOid,
                                                                                 DateTime startTime,
                                                                                 DateTime endTime,
                                                                                 X509ExtensionCollection extensions)
        {
            Debug.Assert(key != null, "key != null");
            Debug.Assert(!key.IsClosed && !key.IsInvalid, "!key.IsClosed && !key.IsInvalid");
            Debug.Assert(subjectName != null, "subjectName != null");
            Debug.Assert(!String.IsNullOrEmpty(signatureAlgorithmOid), "!String.IsNullOrEmpty(signatureAlgorithmOid)");
            Debug.Assert(extensions != null, "extensions != null");

            // Create an algorithm identifier structure for the signature algorithm
            CapiNative.CRYPT_ALGORITHM_IDENTIFIER nativeSignatureAlgorithm = new CapiNative.CRYPT_ALGORITHM_IDENTIFIER();
            nativeSignatureAlgorithm.pszObjId          = signatureAlgorithmOid;
            nativeSignatureAlgorithm.Parameters        = new CapiNative.CRYPTOAPI_BLOB();
            nativeSignatureAlgorithm.Parameters.cbData = 0;
            nativeSignatureAlgorithm.Parameters.pbData = IntPtr.Zero;

            // Convert the begin and expire dates to system time structures
            Win32Native.SYSTEMTIME nativeStartTime = new Win32Native.SYSTEMTIME(startTime);
            Win32Native.SYSTEMTIME nativeEndTime   = new Win32Native.SYSTEMTIME(endTime);

            // Map the extensions into CERT_EXTENSIONS.  This involves several steps to get the
            // CERT_EXTENSIONS ready for interop with the native APIs.
            //   1. Build up the CERT_EXTENSIONS structure in managed code
            //   2. For each extension, create a managed CERT_EXTENSION structure; this requires allocating
            //      native memory for the blob pointer in the CERT_EXTENSION. These extensions are stored in
            //      the nativeExtensionArray variable.
            //   3. Get a block of native memory that can hold a native array of CERT_EXTENSION structures.
            //      This is the block referenced by the CERT_EXTENSIONS structure.
            //   4. For each of the extension structures created in step 2, marshal the extension into the
            //      native buffer allocated in step 3.
            CERT_EXTENSIONS nativeExtensions = new CERT_EXTENSIONS();

            nativeExtensions.cExtension = extensions.Count;
            CERT_EXTENSION[] nativeExtensionArray = new CERT_EXTENSION[extensions.Count];

            // Run this in a CER to ensure that we release any native memory allocated for the certificate
            // extensions.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                // Copy over each extension into a native extension structure, including allocating native
                // memory for its blob if necessary.
                for (int i = 0; i < extensions.Count; ++i)
                {
                    nativeExtensionArray[i]           = new CERT_EXTENSION();
                    nativeExtensionArray[i].pszObjId  = extensions[i].Oid.Value;
                    nativeExtensionArray[i].fCritical = extensions[i].Critical;

                    nativeExtensionArray[i].Value        = new CapiNative.CRYPTOAPI_BLOB();
                    nativeExtensionArray[i].Value.cbData = extensions[i].RawData.Length;
                    if (nativeExtensionArray[i].Value.cbData > 0)
                    {
                        nativeExtensionArray[i].Value.pbData =
                            Marshal.AllocCoTaskMem(nativeExtensionArray[i].Value.cbData);
                        Marshal.Copy(extensions[i].RawData,
                                     0,
                                     nativeExtensionArray[i].Value.pbData,
                                     nativeExtensionArray[i].Value.cbData);
                    }
                }

                // Now that we've built up the extension array, create a block of native memory to marshal
                // them into.
                if (nativeExtensionArray.Length > 0)
                {
                    checked
                    {
                        // CERT_EXTENSION structures end with a pointer field, which means on all supported
                        // platforms they won't require any padding between elements of the array.
                        nativeExtensions.rgExtension =
                            Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(CERT_EXTENSION)) * nativeExtensionArray.Length);

                        for (int i = 0; i < nativeExtensionArray.Length; ++i)
                        {
                            ulong  offset            = (uint)i * (uint)Marshal.SizeOf(typeof(CERT_EXTENSION));
                            ulong  next              = offset + (ulong)nativeExtensions.rgExtension.ToInt64();
                            IntPtr nextExtensionAddr = new IntPtr((long)next);

                            Marshal.StructureToPtr(nativeExtensionArray[i], nextExtensionAddr, false);
                        }
                    }
                }

                //
                // Now that all of the needed data structures are setup, we can create the certificate
                //

                unsafe
                {
                    fixed(byte *pSubjectName = &subjectName[0])
                    {
                        // Create a CRYPTOAPI_BLOB for the subject of the cert
                        CapiNative.CRYPTOAPI_BLOB nativeSubjectName = new CapiNative.CRYPTOAPI_BLOB();
                        nativeSubjectName.cbData = subjectName.Length;
                        nativeSubjectName.pbData = new IntPtr(pSubjectName);

                        // Now that we've converted all the inputs to native data structures, we can generate
                        // the self signed certificate for the input key.
                        SafeCertificateContextHandle selfSignedCertHandle =
                            UnsafeNativeMethods.CertCreateSelfSignCertificate(key,
                                                                              ref nativeSubjectName,
                                                                              creationOptions,
                                                                              IntPtr.Zero,
                                                                              ref nativeSignatureAlgorithm,
                                                                              ref nativeStartTime,
                                                                              ref nativeEndTime,
                                                                              ref nativeExtensions);

                        if (selfSignedCertHandle.IsInvalid)
                        {
                            throw new CryptographicException(Marshal.GetLastWin32Error());
                        }

                        return(selfSignedCertHandle);
                    }
                }
            }
            finally
            {
                //
                // In order to release all resources held by the CERT_EXTENSIONS we need to do three things
                //   1. Destroy each structure marshaled into the native CERT_EXTENSION array
                //   2. Release the memory used for the CERT_EXTENSION array
                //   3. Release the memory used in each individual CERT_EXTENSION
                //

                // Release each extension marshaled into the native buffer as well
                if (nativeExtensions.rgExtension != IntPtr.Zero)
                {
                    for (int i = 0; i < nativeExtensionArray.Length; ++i)
                    {
                        ulong  offset            = (uint)i * (uint)Marshal.SizeOf(typeof(CERT_EXTENSION));
                        ulong  next              = offset + (ulong)nativeExtensions.rgExtension.ToInt64();
                        IntPtr nextExtensionAddr = new IntPtr((long)next);

                        Marshal.DestroyStructure(nextExtensionAddr, typeof(CERT_EXTENSION));
                    }

                    Marshal.FreeCoTaskMem(nativeExtensions.rgExtension);
                }

                // If we allocated memory for any extensions, make sure to free it now
                for (int i = 0; i < nativeExtensionArray.Length; ++i)
                {
                    if (nativeExtensionArray[i].Value.pbData != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(nativeExtensionArray[i].Value.pbData);
                    }
                }
            }
        }
예제 #6
0
 internal static extern SafeCertificateContextHandle CertCreateSelfSignCertificate(SafeNCryptKeyHandle hCryptProvOrNCryptKey,
                                                                                   [In] ref CapiNative.CRYPTOAPI_BLOB pSubjectIssuerBlob,
                                                                                   X509CertificateCreationOptions dwFlags,
                                                                                   IntPtr pKeyProvInfo, // PCRYPT_KEY_PROV_INFO
                                                                                   [In] ref CapiNative.CRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm,
                                                                                   [In] ref Win32Native.SYSTEMTIME pStartTime,
                                                                                   [In] ref Win32Native.SYSTEMTIME pEndTime,
                                                                                   [In] ref CERT_EXTENSIONS pExtensions);
예제 #7
0
 public static extern int CertVerifyAuthenticodeLicense(ref CapiNative.CRYPTOAPI_BLOB pLicenseBlob,
                                                        AxlVerificationFlags dwFlags,
                                                        [In, Out] ref AXL_AUTHENTICODE_SIGNER_INFO pSignerInfo,
                                                        [In, Out] ref AXL_AUTHENTICODE_TIMESTAMPER_INFO pTimestamperInfo);
        private AuthenticodeSignatureInformation VerifyAuthenticodeSignature(XmlElement signatureNode,
                                                                             X509RevocationFlag revocationFlag,
                                                                             X509RevocationMode revocationMode) {
            Debug.Assert(signatureNode != null, "signatureNode != null");

            // See if there is an Authenticode signature on the manifest
            XmlElement licenseNode = signatureNode.SelectSingleNode("ds:KeyInfo/msrel:RelData/r:license",
                                                                     m_namespaceManager) as XmlElement;
            if (licenseNode == null) {
                return null;
            }

            // Make sure that the signature is for this manifest
            SignatureVerificationResult identityVerification = VerifyAuthenticodeSignatureIdentity(licenseNode);
            if (identityVerification != SignatureVerificationResult.Valid) {
                return new AuthenticodeSignatureInformation(identityVerification);
            }

            SignatureVerificationResult hashVerification = VerifyAuthenticodeExpectedHash(licenseNode);
            if (hashVerification != SignatureVerificationResult.Valid) {
                return new AuthenticodeSignatureInformation(hashVerification);
            }

            // Verify the signature, extracting information about it
            AuthenticodeSignatureInformation authenticodeSignature = null;

            X509Native.AXL_AUTHENTICODE_SIGNER_INFO signer = new X509Native.AXL_AUTHENTICODE_SIGNER_INFO();
            signer.cbSize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_SIGNER_INFO));

            X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO timestamper = new X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO();
            timestamper.cbsize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO));

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                byte[] licenseXml = Encoding.UTF8.GetBytes(licenseNode.OuterXml);
                X509Native.AxlVerificationFlags verificationFlags = MapRevocationFlags(revocationFlag,
                                                                                       revocationMode);

                unsafe {
                    fixed (byte* pLicenseXml = licenseXml) {
                        // Safe since we're verifying the size of this buffer is correct
                        CapiNative.CRYPTOAPI_BLOB xmlBlob = new CapiNative.CRYPTOAPI_BLOB();
                        xmlBlob.cbData = licenseXml.Length;
                        xmlBlob.pbData = new IntPtr(pLicenseXml);

                        int hrVerify = X509Native.UnsafeNativeMethods.CertVerifyAuthenticodeLicense(ref xmlBlob,
                                                                                                    verificationFlags,
                                                                                                    ref signer,
                                                                                                    ref timestamper);

                        if (hrVerify == (int)SignatureVerificationResult.MissingSignature) {
                            return new AuthenticodeSignatureInformation(SignatureVerificationResult.MissingSignature);
                        }
                    }
                }

                X509Chain signatureChain = BuildSignatureChain(signer,
                                                               licenseNode,
                                                               revocationFlag,
                                                               revocationMode);

                TimestampInformation timestamp = GetTimestampInformation(timestamper,
                                                                         licenseNode);

                authenticodeSignature = new AuthenticodeSignatureInformation(signer,
                                                                             signatureChain,
                                                                             timestamp);
            }
            finally {
                X509Native.UnsafeNativeMethods.CertFreeAuthenticodeSignerInfo(ref signer);
                X509Native.UnsafeNativeMethods.CertFreeAuthenticodeTimestamperInfo(ref timestamper);
            }

            // Verify the signing certificate matches the expected publisher
            Debug.Assert(authenticodeSignature != null, "authenticodeSignature != null");
            if (authenticodeSignature.SigningCertificate == null) {
                return new AuthenticodeSignatureInformation(authenticodeSignature.VerificationResult);
            }

            SignatureVerificationResult publisherMatch = VerifyAuthenticodePublisher(authenticodeSignature.SigningCertificate);
            if (publisherMatch != SignatureVerificationResult.Valid) {
                return new AuthenticodeSignatureInformation(publisherMatch);
            }

            return authenticodeSignature;
        }
        private static byte[] CalculateSignerPublicKeyToken(AsymmetricAlgorithm key) {
            Debug.Assert(key != null, "key != null");

            ICspAsymmetricAlgorithm cspAlgorithm = key as ICspAsymmetricAlgorithm;
            if (cspAlgorithm == null) {
                return null;
            }

            byte[] publicKey = cspAlgorithm.ExportCspBlob(false);
            SafeAxlBufferHandle tokenBuffer;

            unsafe {
                fixed (byte* pPublicKey = publicKey) {
                    // Safe, since we're ensuring the CAPI buffer going in is sized correctly
                    CapiNative.CRYPTOAPI_BLOB keyBlob = new CapiNative.CRYPTOAPI_BLOB();
                    keyBlob.cbData = publicKey.Length;
                    keyBlob.pbData = new IntPtr(pPublicKey);

                    int hrToken = CapiNative.UnsafeNativeMethods._AxlPublicKeyBlobToPublicKeyToken(ref keyBlob,
                                                                                                   out tokenBuffer);
                    if (((uint)hrToken & 0x80000000) != 0) {
                        return null;
                    }
                }
            }

            bool acquired = false;

            RuntimeHelpers.PrepareConstrainedRegions();
            try {
                tokenBuffer.DangerousAddRef(ref acquired);
                return HexStringToBytes(Marshal.PtrToStringUni(tokenBuffer.DangerousGetHandle()));
            }
            finally {
                if (acquired) {
                    tokenBuffer.DangerousRelease();
                }
            }
        }
예제 #10
0
        internal static SafeCertContextHandle CreateSelfSignedCertificate(CngKey key,
                                                                          bool takeOwnershipOfKey,
                                                                          byte[] subjectName,
                                                                          X509CertificateCreationOptions creationOptions,
                                                                          string signatureAlgorithmOid,
                                                                          DateTime startTime,
                                                                          DateTime endTime,
                                                                          X509ExtensionCollection extensions)
        {
            Debug.Assert(key != null, "key != null");
            Debug.Assert(subjectName != null, "subjectName != null");
            Debug.Assert(!String.IsNullOrEmpty(signatureAlgorithmOid), "!String.IsNullOrEmpty(signatureAlgorithmOid)");
            Debug.Assert(extensions != null, "extensions != null");

            // Create an algorithm identifier structure for the signature algorithm
            CapiNative.CRYPT_ALGORITHM_IDENTIFIER nativeSignatureAlgorithm = new CapiNative.CRYPT_ALGORITHM_IDENTIFIER();
            nativeSignatureAlgorithm.pszObjId          = signatureAlgorithmOid;
            nativeSignatureAlgorithm.Parameters        = new CapiNative.CRYPTOAPI_BLOB();
            nativeSignatureAlgorithm.Parameters.cbData = 0;
            nativeSignatureAlgorithm.Parameters.pbData = IntPtr.Zero;

            // Convert the begin and expire dates to system time structures
            Win32Native.SYSTEMTIME nativeStartTime = new Win32Native.SYSTEMTIME(startTime);
            Win32Native.SYSTEMTIME nativeEndTime   = new Win32Native.SYSTEMTIME(endTime);

            // Map the extensions into CERT_EXTENSIONS.  This involves several steps to get the
            // CERT_EXTENSIONS ready for interop with the native APIs.
            //   1. Build up the CERT_EXTENSIONS structure in managed code
            //   2. For each extension, create a managed CERT_EXTENSION structure; this requires allocating
            //      native memory for the blob pointer in the CERT_EXTENSION. These extensions are stored in
            //      the nativeExtensionArray variable.
            //   3. Get a block of native memory that can hold a native array of CERT_EXTENSION structures.
            //      This is the block referenced by the CERT_EXTENSIONS structure.
            //   4. For each of the extension structures created in step 2, marshal the extension into the
            //      native buffer allocated in step 3.
            CERT_EXTENSIONS nativeExtensions = new CERT_EXTENSIONS();

            nativeExtensions.cExtension = extensions.Count;
            CERT_EXTENSION[] nativeExtensionArray = new CERT_EXTENSION[extensions.Count];

            // Run this in a CER to ensure that we release any native memory allocated for the certificate
            // extensions.
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                // Copy over each extension into a native extension structure, including allocating native
                // memory for its blob if necessary.
                for (int i = 0; i < extensions.Count; ++i)
                {
                    nativeExtensionArray[i]           = new CERT_EXTENSION();
                    nativeExtensionArray[i].pszObjId  = extensions[i].Oid.Value;
                    nativeExtensionArray[i].fCritical = extensions[i].Critical;

                    nativeExtensionArray[i].Value        = new CapiNative.CRYPTOAPI_BLOB();
                    nativeExtensionArray[i].Value.cbData = extensions[i].RawData.Length;
                    if (nativeExtensionArray[i].Value.cbData > 0)
                    {
                        nativeExtensionArray[i].Value.pbData =
                            Marshal.AllocCoTaskMem(nativeExtensionArray[i].Value.cbData);
                        Marshal.Copy(extensions[i].RawData,
                                     0,
                                     nativeExtensionArray[i].Value.pbData,
                                     nativeExtensionArray[i].Value.cbData);
                    }
                }

                // Now that we've built up the extension array, create a block of native memory to marshal
                // them into.
                if (nativeExtensionArray.Length > 0)
                {
                    checked
                    {
                        // CERT_EXTENSION structures end with a pointer field, which means on all supported
                        // platforms they won't require any padding between elements of the array.
                        nativeExtensions.rgExtension =
                            Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(CERT_EXTENSION)) * nativeExtensionArray.Length);

                        for (int i = 0; i < nativeExtensionArray.Length; ++i)
                        {
                            ulong  offset            = (uint)i * (uint)Marshal.SizeOf(typeof(CERT_EXTENSION));
                            ulong  next              = offset + (ulong)nativeExtensions.rgExtension.ToInt64();
                            IntPtr nextExtensionAddr = new IntPtr((long)next);

                            Marshal.StructureToPtr(nativeExtensionArray[i], nextExtensionAddr, false);
                        }
                    }
                }

                // Setup a CRYPT_KEY_PROV_INFO for the key
                CRYPT_KEY_PROV_INFO keyProvInfo = new CRYPT_KEY_PROV_INFO();
                keyProvInfo.pwszContainerName = key.UniqueName;
                keyProvInfo.pwszProvName      = key.Provider.Provider;
                keyProvInfo.dwProvType        = 0; // NCRYPT
                keyProvInfo.dwFlags           = 0;
                keyProvInfo.cProvParam        = 0;
                keyProvInfo.rgProvParam       = IntPtr.Zero;
                keyProvInfo.dwKeySpec         = 0;

                //
                // Now that all of the needed data structures are setup, we can create the certificate
                //

                SafeCertContextHandle selfSignedCertHandle = null;
                unsafe
                {
                    fixed(byte *pSubjectName = &subjectName[0])
                    {
                        // Create a CRYPTOAPI_BLOB for the subject of the cert
                        CapiNative.CRYPTOAPI_BLOB nativeSubjectName = new CapiNative.CRYPTOAPI_BLOB();
                        nativeSubjectName.cbData = subjectName.Length;
                        nativeSubjectName.pbData = new IntPtr(pSubjectName);

                        // Now that we've converted all the inputs to native data structures, we can generate
                        // the self signed certificate for the input key.
                        using (SafeNCryptKeyHandle keyHandle = key.Handle)
                        {
                            selfSignedCertHandle =
                                UnsafeNativeMethods.CertCreateSelfSignCertificate(keyHandle,
                                                                                  ref nativeSubjectName,
                                                                                  creationOptions,
                                                                                  ref keyProvInfo,
                                                                                  ref nativeSignatureAlgorithm,
                                                                                  ref nativeStartTime,
                                                                                  ref nativeEndTime,
                                                                                  ref nativeExtensions);
                            if (selfSignedCertHandle.IsInvalid)
                            {
                                throw new CryptographicException(Marshal.GetLastWin32Error());
                            }
                        }
                    }
                }

                Debug.Assert(selfSignedCertHandle != null, "selfSignedCertHandle != null");

                // Attach a key context to the certificate which will allow Windows to find the private key
                // associated with the certificate if the NCRYPT_KEY_HANDLE is ephemeral.
                // is done.
                using (SafeNCryptKeyHandle keyHandle = key.Handle)
                {
                    CERT_KEY_CONTEXT keyContext = new CERT_KEY_CONTEXT();
                    keyContext.cbSize     = Marshal.SizeOf(typeof(CERT_KEY_CONTEXT));
                    keyContext.hNCryptKey = keyHandle.DangerousGetHandle();
                    keyContext.dwKeySpec  = KeySpec.NCryptKey;

                    bool attachedProperty = false;
                    int  setContextError  = 0;

                    // Run in a CER to ensure accurate tracking of the transfer of handle ownership
                    RuntimeHelpers.PrepareConstrainedRegions();
                    try { }
                    finally
                    {
                        CertificatePropertySetFlags flags = CertificatePropertySetFlags.None;
                        if (!takeOwnershipOfKey)
                        {
                            // If the certificate is not taking ownership of the key handle, then it should
                            // not release the handle when the context is released.
                            flags |= CertificatePropertySetFlags.NoCryptRelease;
                        }

                        attachedProperty =
                            UnsafeNativeMethods.CertSetCertificateContextProperty(selfSignedCertHandle,
                                                                                  CertificateProperty.KeyContext,
                                                                                  flags,
                                                                                  ref keyContext);
                        setContextError = Marshal.GetLastWin32Error();

                        // If we succesfully transferred ownership of the key to the certificate,
                        // then we need to ensure that we no longer release its handle.
                        if (attachedProperty && takeOwnershipOfKey)
                        {
                            keyHandle.SetHandleAsInvalid();
                        }
                    }

                    if (!attachedProperty)
                    {
                        throw new CryptographicException(setContextError);
                    }
                }

                return(selfSignedCertHandle);
            }
            finally
            {
                //
                // In order to release all resources held by the CERT_EXTENSIONS we need to do three things
                //   1. Destroy each structure marshaled into the native CERT_EXTENSION array
                //   2. Release the memory used for the CERT_EXTENSION array
                //   3. Release the memory used in each individual CERT_EXTENSION
                //

                // Release each extension marshaled into the native buffer as well
                if (nativeExtensions.rgExtension != IntPtr.Zero)
                {
                    for (int i = 0; i < nativeExtensionArray.Length; ++i)
                    {
                        ulong  offset            = (uint)i * (uint)Marshal.SizeOf(typeof(CERT_EXTENSION));
                        ulong  next              = offset + (ulong)nativeExtensions.rgExtension.ToInt64();
                        IntPtr nextExtensionAddr = new IntPtr((long)next);

                        Marshal.DestroyStructure(nextExtensionAddr, typeof(CERT_EXTENSION));
                    }

                    Marshal.FreeCoTaskMem(nativeExtensions.rgExtension);
                }

                // If we allocated memory for any extensions, make sure to free it now
                for (int i = 0; i < nativeExtensionArray.Length; ++i)
                {
                    if (nativeExtensionArray[i].Value.pbData != IntPtr.Zero)
                    {
                        Marshal.FreeCoTaskMem(nativeExtensionArray[i].Value.pbData);
                    }
                }
            }
        }
 private static unsafe byte[] CalculateSignerPublicKeyToken(AsymmetricAlgorithm key)
 {
     SafeAxlBufferHandle handle;
     byte[] buffer2;
     ICspAsymmetricAlgorithm algorithm = key as ICspAsymmetricAlgorithm;
     if (algorithm == null)
     {
         return null;
     }
     byte[] buffer = algorithm.ExportCspBlob(false);
     fixed (byte* numRef = buffer)
     {
         CapiNative.CRYPTOAPI_BLOB pCspPublicKeyBlob = new CapiNative.CRYPTOAPI_BLOB {
             cbData = buffer.Length,
             pbData = new IntPtr((void*) numRef)
         };
         if ((CapiNative.UnsafeNativeMethods._AxlPublicKeyBlobToPublicKeyToken(ref pCspPublicKeyBlob, out handle) & -2147483648) != 0)
         {
             return null;
         }
     }
     bool success = false;
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         handle.DangerousAddRef(ref success);
         buffer2 = HexStringToBytes(Marshal.PtrToStringUni(handle.DangerousGetHandle()));
     }
     finally
     {
         if (success)
         {
             handle.DangerousRelease();
         }
     }
     return buffer2;
 }
 private unsafe AuthenticodeSignatureInformation VerifyAuthenticodeSignature(XmlElement signatureNode, X509RevocationFlag revocationFlag, X509RevocationMode revocationMode)
 {
     XmlElement licenseNode = signatureNode.SelectSingleNode("ds:KeyInfo/msrel:RelData/r:license", this.m_namespaceManager) as XmlElement;
     if (licenseNode == null)
     {
         return null;
     }
     SignatureVerificationResult error = this.VerifyAuthenticodeSignatureIdentity(licenseNode);
     if (error != SignatureVerificationResult.Valid)
     {
         return new AuthenticodeSignatureInformation(error);
     }
     SignatureVerificationResult result2 = this.VerifyAuthenticodeExpectedHash(licenseNode);
     if (result2 != SignatureVerificationResult.Valid)
     {
         return new AuthenticodeSignatureInformation(result2);
     }
     AuthenticodeSignatureInformation information = null;
     X509Native.AXL_AUTHENTICODE_SIGNER_INFO pSignerInfo = new X509Native.AXL_AUTHENTICODE_SIGNER_INFO {
         cbSize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_SIGNER_INFO))
     };
     X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO pTimestamperInfo = new X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO {
         cbsize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO))
     };
     RuntimeHelpers.PrepareConstrainedRegions();
     try
     {
         byte[] bytes = Encoding.UTF8.GetBytes(licenseNode.OuterXml);
         X509Native.AxlVerificationFlags dwFlags = MapRevocationFlags(revocationFlag, revocationMode);
         try
         {
             fixed (byte* numRef = bytes)
             {
                 CapiNative.CRYPTOAPI_BLOB pLicenseBlob = new CapiNative.CRYPTOAPI_BLOB {
                     cbData = bytes.Length,
                     pbData = new IntPtr((void*) numRef)
                 };
                 if (X509Native.UnsafeNativeMethods.CertVerifyAuthenticodeLicense(ref pLicenseBlob, dwFlags, ref pSignerInfo, ref pTimestamperInfo) == -2146762496)
                 {
                     return new AuthenticodeSignatureInformation(SignatureVerificationResult.MissingSignature);
                 }
             }
         }
         finally
         {
             numRef = null;
         }
         X509Chain signatureChain = this.BuildSignatureChain(pSignerInfo, licenseNode, revocationFlag, revocationMode);
         TimestampInformation timestampInformation = this.GetTimestampInformation(pTimestamperInfo, licenseNode);
         information = new AuthenticodeSignatureInformation(pSignerInfo, signatureChain, timestampInformation);
     }
     finally
     {
         X509Native.UnsafeNativeMethods.CertFreeAuthenticodeSignerInfo(ref pSignerInfo);
         X509Native.UnsafeNativeMethods.CertFreeAuthenticodeTimestamperInfo(ref pTimestamperInfo);
     }
     if (information.SigningCertificate == null)
     {
         return new AuthenticodeSignatureInformation(information.VerificationResult);
     }
     SignatureVerificationResult result3 = this.VerifyAuthenticodePublisher(information.SigningCertificate);
     if (result3 != SignatureVerificationResult.Valid)
     {
         return new AuthenticodeSignatureInformation(result3);
     }
     return information;
 }
예제 #13
0
        private unsafe AuthenticodeSignatureInformation VerifyAuthenticodeSignature(XmlElement signatureNode, X509RevocationFlag revocationFlag, X509RevocationMode revocationMode)
        {
            XmlElement licenseNode = signatureNode.SelectSingleNode("ds:KeyInfo/msrel:RelData/r:license", this.m_namespaceManager) as XmlElement;

            if (licenseNode == null)
            {
                return(null);
            }
            SignatureVerificationResult error = this.VerifyAuthenticodeSignatureIdentity(licenseNode);

            if (error != SignatureVerificationResult.Valid)
            {
                return(new AuthenticodeSignatureInformation(error));
            }
            SignatureVerificationResult result2 = this.VerifyAuthenticodeExpectedHash(licenseNode);

            if (result2 != SignatureVerificationResult.Valid)
            {
                return(new AuthenticodeSignatureInformation(result2));
            }
            AuthenticodeSignatureInformation information = null;

            X509Native.AXL_AUTHENTICODE_SIGNER_INFO pSignerInfo = new X509Native.AXL_AUTHENTICODE_SIGNER_INFO {
                cbSize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_SIGNER_INFO))
            };
            X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO pTimestamperInfo = new X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO {
                cbsize = Marshal.SizeOf(typeof(X509Native.AXL_AUTHENTICODE_TIMESTAMPER_INFO))
            };
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                byte[] bytes = Encoding.UTF8.GetBytes(licenseNode.OuterXml);
                X509Native.AxlVerificationFlags dwFlags = MapRevocationFlags(revocationFlag, revocationMode);
                try
                {
                    fixed(byte *numRef = bytes)
                    {
                        CapiNative.CRYPTOAPI_BLOB pLicenseBlob = new CapiNative.CRYPTOAPI_BLOB {
                            cbData = bytes.Length,
                            pbData = new IntPtr((void *)numRef)
                        };
                        if (X509Native.UnsafeNativeMethods.CertVerifyAuthenticodeLicense(ref pLicenseBlob, dwFlags, ref pSignerInfo, ref pTimestamperInfo) == -2146762496)
                        {
                            return(new AuthenticodeSignatureInformation(SignatureVerificationResult.MissingSignature));
                        }
                    }
                }
                finally
                {
                    numRef = null;
                }
                X509Chain            signatureChain       = this.BuildSignatureChain(pSignerInfo, licenseNode, revocationFlag, revocationMode);
                TimestampInformation timestampInformation = this.GetTimestampInformation(pTimestamperInfo, licenseNode);
                information = new AuthenticodeSignatureInformation(pSignerInfo, signatureChain, timestampInformation);
            }
            finally
            {
                X509Native.UnsafeNativeMethods.CertFreeAuthenticodeSignerInfo(ref pSignerInfo);
                X509Native.UnsafeNativeMethods.CertFreeAuthenticodeTimestamperInfo(ref pTimestamperInfo);
            }
            if (information.SigningCertificate == null)
            {
                return(new AuthenticodeSignatureInformation(information.VerificationResult));
            }
            SignatureVerificationResult result3 = this.VerifyAuthenticodePublisher(information.SigningCertificate);

            if (result3 != SignatureVerificationResult.Valid)
            {
                return(new AuthenticodeSignatureInformation(result3));
            }
            return(information);
        }