Ejemplo n.º 1
0
            public static Signer GetSignerFromStateData(IntPtr StateData)
            {
                // Sanity check
                if (StateData == IntPtr.Zero)
                {
                    return(null);
                }

                // 1. Get provider data from state data
                IntPtr pProvData = WTHelperProvDataFromStateData(StateData);

                if (pProvData == IntPtr.Zero)
                {
                    return(null);
                }
                CryptProviderData provData = (CryptProviderData)Marshal.PtrToStructure(pProvData, typeof(CryptProviderData));

                // 2. Get provider signer from provider data
                IntPtr pSgnr = WTHelperGetProvSignerFromChain(pProvData, 0, false, 0);

                if (pSgnr == IntPtr.Zero)
                {
                    return(null);
                }

                CryptProviderSgnr sgnr = (CryptProviderSgnr)Marshal.PtrToStructure(pSgnr, typeof(CryptProviderSgnr));

                if (sgnr.pasCertChain == null)
                {
                    return(null);
                }
                if (sgnr.csCertChain == 0)
                {
                    return(null);
                }

                // 3. Get provider cert from provider signer
                var providerCerts            = new List <CryptProviderCert>();
                var ptr                      = sgnr.pasCertChain;
                int sizeof_cryptProviderCert = Marshal.SizeOf(new CryptProviderCert());

                // Collect certificate chain into a list
                for (int i = 0; i < sgnr.csCertChain; i++)
                {
                    providerCerts.Add((CryptProviderCert)Marshal.PtrToStructure(ptr, typeof(CryptProviderCert)));
                    ptr = (IntPtr)((int)ptr + sizeof_cryptProviderCert);

                    // Sanity check
                    const int MAX_CERT_CHAIN_LENGTH = 20; // Arbitrary max length of a chain I'm willing to use
                    if (i > MAX_CERT_CHAIN_LENGTH)
                    {
                        break;
                    }
                }

                // This is actually a list, but I only care about the first element
                CryptProviderCert cert = providerCerts[0];

                // 4. Get cert context
                CertContext certContext = (CertContext)Marshal.PtrToStructure(cert.pCert, typeof(CertContext));

                // 5. Get cert info
                CertInfo certInfo = (CertInfo)Marshal.PtrToStructure(certContext.pCertInfo, typeof(CertInfo));

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

                CRYPTOAPI_BLOB subject = certInfo.Subject;

                // 6. Get subject X.500 string
                string issuer = GetCertIssuerString(subject);

                // Get the best name for identifying this cert
                X500DistinguishedName x500DN = new X500DistinguishedName(issuer);
                string signerName            = getBestName(x500DN);

                // Clean up the signer name
                signerName = signerName.Replace("\"", "");
                signerName = signerName.Trim();  // Remove trailing "\x0d"

                int serialNumberLen = certInfo.SerialNumber.cbData;

                if (serialNumberLen < 0 || serialNumberLen > 256)
                {
                    // TODO Should throw an error
                }
                var serialNumber = new byte[serialNumberLen];

                Marshal.Copy(certInfo.SerialNumber.pbData, serialNumber, 0, serialNumberLen);
                // Byte order seems to be reversed, so I'm flipping it here
                Array.Reverse(serialNumber, 0, serialNumberLen);


                var certEntity = new Certificate {
                    Version                   = certInfo.dwVersion,
                    Issuer                    = issuer,
                    SerialNumber              = serialNumber,
                    DigestAlgorithm           = certInfo.SignatureAlgorithm.pszObjId,
                    DigestEncryptionAlgorithm = certInfo.SubjectPublicKeyInfoAlgo.Algorithm.pszObjId
                };

                var signer = new Signer
                {
                    Name        = signerName,
                    Timestamp   = DateTime.FromFileTime((long)sgnr.sftVerifyAsOf),
                    SigningCert = certEntity
                };

                return(signer);
            }
Ejemplo n.º 2
0
        private static string GetSignerNameFromStateData(IntPtr stateData)
        {
            // Well, here's a shitload of indirection for you...

            // 1. State data -> Provider data
            IntPtr provData = Win32.WTHelperProvDataFromStateData(stateData);

            if (provData == IntPtr.Zero)
            {
                return(null);
            }

            // 2. Provider data -> Provider signer
            IntPtr signerInfo = Win32.WTHelperGetProvSignerFromChain(provData, 0, false, 0);

            if (signerInfo == IntPtr.Zero)
            {
                return(null);
            }

            CryptProviderSgnr sngr = (CryptProviderSgnr)Marshal.PtrToStructure(signerInfo, typeof(CryptProviderSgnr));

            if (sngr.CertChain == IntPtr.Zero)
            {
                return(null);
            }
            if (sngr.CertChainCount == 0)
            {
                return(null);
            }

            // 3. Provider signer -> Provider cert
            CryptProviderCert cert = (CryptProviderCert)Marshal.PtrToStructure(sngr.CertChain, typeof(CryptProviderCert));

            if (cert.Cert == IntPtr.Zero)
            {
                return(null);
            }

            // 4. Provider cert -> Cert context
            CertContext context = (CertContext)Marshal.PtrToStructure(cert.Cert, typeof(CertContext));

            if (context.CertInfo != IntPtr.Zero)
            {
                // 5. Cert context -> Cert info
                CertInfo certInfo = (CertInfo)Marshal.PtrToStructure(context.CertInfo, typeof(CertInfo));

                unsafe
                {
                    using (MemoryAlloc buffer = new MemoryAlloc(0x200))
                    {
                        int length;

                        // 6. Cert info subject -> Subject X.500 string

                        length = Win32.CertNameToStr(
                            1,
                            new IntPtr(&certInfo.Subject),
                            3,
                            buffer,
                            buffer.Size / 2
                            );

                        if (length > buffer.Size / 2)
                        {
                            buffer.ResizeNew(length * 2);

                            length = Win32.CertNameToStr(
                                1,
                                new IntPtr(&certInfo.Subject),
                                3,
                                buffer,
                                buffer.Size / 2
                                );
                        }

                        string name = buffer.ReadUnicodeString(0);

                        // 7. Subject X.500 string -> CN or OU value

                        string value = GetX500Value(name, "CN");

                        if (string.IsNullOrEmpty(value))
                        {
                            value = GetX500Value(name, "OU");
                        }

                        return(value);
                    }
                }
            }

            return(null);
        }