Example #1
0
        private unsafe static CMSG_SIGNER_ENCODE_INFO CreateSignerInfo(
            CmsSigner cmsSigner,
            CngKey privateKey,
            HeapBlockRetainer hb)
        {
            var signerInfo = new CMSG_SIGNER_ENCODE_INFO();

            signerInfo.cbSize    = (uint)Marshal.SizeOf(signerInfo);
            signerInfo.pCertInfo = Marshal.PtrToStructure <CERT_CONTEXT>(cmsSigner.Certificate.Handle).pCertInfo;
            signerInfo.hCryptProvOrhNCryptKey = privateKey.Handle.DangerousGetHandle();
            signerInfo.HashAlgorithm.pszObjId = cmsSigner.DigestAlgorithm.Value;

            if (cmsSigner.SignerIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier)
            {
                var certContextHandle = IntPtr.Zero;

                try
                {
                    certContextHandle = NativeMethods.CertDuplicateCertificateContext(cmsSigner.Certificate.Handle);

                    uint cbData = 0;
                    var  pbData = IntPtr.Zero;

                    ThrowIfFailed(NativeMethods.CertGetCertificateContextProperty(
                                      certContextHandle,
                                      NativeMethods.CERT_KEY_IDENTIFIER_PROP_ID,
                                      pbData,
                                      ref cbData));

                    if (cbData > 0)
                    {
                        pbData = hb.Alloc((int)cbData);

                        ThrowIfFailed(NativeMethods.CertGetCertificateContextProperty(
                                          certContextHandle,
                                          NativeMethods.CERT_KEY_IDENTIFIER_PROP_ID,
                                          pbData,
                                          ref cbData));

                        signerInfo.SignerId.dwIdChoice   = NativeMethods.CERT_ID_KEY_IDENTIFIER;
                        signerInfo.SignerId.KeyId.cbData = cbData;
                        signerInfo.SignerId.KeyId.pbData = pbData;
                    }
                }
                finally
                {
                    if (certContextHandle != IntPtr.Zero)
                    {
                        NativeMethods.CertFreeCertificateContext(certContextHandle);
                    }
                }
            }

            if (cmsSigner.SignedAttributes.Count != 0)
            {
                signerInfo.cAuthAttr = cmsSigner.SignedAttributes.Count;

                checked
                {
                    var attributeSize    = Marshal.SizeOf <CRYPT_ATTRIBUTE>();
                    var blobSize         = Marshal.SizeOf <CRYPT_INTEGER_BLOB>();
                    var attributesArray  = (CRYPT_ATTRIBUTE *)hb.Alloc(attributeSize * cmsSigner.SignedAttributes.Count);
                    var currentAttribute = attributesArray;

                    foreach (var attribute in cmsSigner.SignedAttributes)
                    {
                        currentAttribute->pszObjId = hb.AllocAsciiString(attribute.Oid.Value);
                        currentAttribute->cValue   = (uint)attribute.Values.Count;
                        currentAttribute->rgValue  = hb.Alloc(blobSize);

                        foreach (var value in attribute.Values)
                        {
                            var attrData = value.RawData;

                            if (attrData.Length > 0)
                            {
                                var blob = (CRYPT_INTEGER_BLOB *)currentAttribute->rgValue;

                                blob->cbData = (uint)attrData.Length;
                                blob->pbData = hb.Alloc(value.RawData.Length);

                                Marshal.Copy(attrData, 0, blob->pbData, attrData.Length);
                            }
                        }

                        currentAttribute++;
                    }

                    signerInfo.rgAuthAttr = new IntPtr(attributesArray);
                }
            }

            return(signerInfo);
        }
Example #2
0
 public static extern bool CryptMsgCountersign(
     SafeCryptMsgHandle hCryptMsg,
     uint dwIndex,
     int cCountersigners,
     CMSG_SIGNER_ENCODE_INFO rgCountersigners);