Ejemplo n.º 1
0
        private static CRYPT_ATTRIBUTE GetCryptAttributeForData(byte[] data, string attributeOid, HeapBlockRetainer hb)
        {
            var unmanagedData = hb.Alloc(data.Length);

            Marshal.Copy(data, 0, unmanagedData, data.Length);
            var blob = new CRYPT_INTEGER_BLOB()
            {
                cbData = (uint)data.Length,
                pbData = unmanagedData
            };

            var unmanagedBlob = hb.Alloc(Marshal.SizeOf(blob));

            Marshal.StructureToPtr(blob, unmanagedBlob, fDeleteOld: false);

            var attr = new CRYPT_ATTRIBUTE()
            {
                pszObjId = hb.AllocAsciiString(attributeOid),
                cValue   = 1,
                rgValue  = unmanagedBlob
            };

            return(attr);
        }
Ejemplo n.º 2
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);
        }
Ejemplo n.º 3
0
        internal unsafe void AddTimestamp(byte[] timeStampCms)
        {
            using (var hb = new HeapBlockRetainer())
            {
                var unmanagedTimestamp = hb.Alloc(timeStampCms.Length);
                Marshal.Copy(timeStampCms, 0, unmanagedTimestamp, timeStampCms.Length);
                var blob = new CRYPT_INTEGER_BLOB()
                {
                    cbData = (uint)timeStampCms.Length,
                    pbData = unmanagedTimestamp
                };
                var unmanagedBlob = hb.Alloc(Marshal.SizeOf(blob));
                Marshal.StructureToPtr(blob, unmanagedBlob, fDeleteOld: false);

                var attr = new CRYPT_ATTRIBUTE()
                {
                    pszObjId = hb.AllocAsciiString(Oids.SignatureTimeStampTokenAttribute),
                    cValue   = 1,
                    rgValue  = unmanagedBlob
                };
                var unmanagedAttr = hb.Alloc(Marshal.SizeOf(attr));
                Marshal.StructureToPtr(attr, unmanagedAttr, fDeleteOld: false);

                uint encodedLength = 0;
                if (!NativeMethods.CryptEncodeObjectEx(
                        dwCertEncodingType: NativeMethods.X509_ASN_ENCODING | NativeMethods.PKCS_7_ASN_ENCODING,
                        lpszStructType: new IntPtr(NativeMethods.PKCS_ATTRIBUTE),
                        pvStructInfo: unmanagedAttr,
                        dwFlags: 0,
                        pEncodePara: IntPtr.Zero,
                        pvEncoded: IntPtr.Zero,
                        pcbEncoded: ref encodedLength))
                {
                    var err = Marshal.GetLastWin32Error();
                    if (err != NativeMethods.ERROR_MORE_DATA)
                    {
                        Marshal.ThrowExceptionForHR(NativeMethods.GetHRForWin32Error(err));
                    }
                }

                var unmanagedEncoded = hb.Alloc((int)encodedLength);
                if (!NativeMethods.CryptEncodeObjectEx(
                        dwCertEncodingType: NativeMethods.X509_ASN_ENCODING | NativeMethods.PKCS_7_ASN_ENCODING,
                        lpszStructType: new IntPtr(NativeMethods.PKCS_ATTRIBUTE),
                        pvStructInfo: unmanagedAttr,
                        dwFlags: 0,
                        pEncodePara: IntPtr.Zero,
                        pvEncoded: unmanagedEncoded,
                        pcbEncoded: ref encodedLength))
                {
                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                }

                var addAttr = new CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA()
                {
                    dwSignerIndex = 0,
                    BLOB          = new CRYPT_INTEGER_BLOB()
                    {
                        cbData = encodedLength,
                        pbData = unmanagedEncoded
                    }
                };
                addAttr.cbSize = (uint)Marshal.SizeOf(addAttr);
                var unmanagedAddAttr = hb.Alloc(Marshal.SizeOf(addAttr));
                Marshal.StructureToPtr(addAttr, unmanagedAddAttr, fDeleteOld: false);

                if (!NativeMethods.CryptMsgControl(
                        _handle,
                        dwFlags: 0,
                        dwCtrlType: CMSG_CONTROL_TYPE.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR,
                        pvCtrlPara: unmanagedAddAttr))
                {
                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                }
            }
        }
Ejemplo n.º 4
0
        internal unsafe void AddTimestampToRepositoryCountersignature(SignedCms timestamp)
        {
            using (var hb = new HeapBlockRetainer())
            {
                var repositoryCountersignature = GetRepositoryCountersignature(hb);
                if (repositoryCountersignature == null)
                {
                    throw new SignatureException(Strings.Error_NotOneRepositoryCounterSignature);
                }

                // Remove repository countersignature from message
                var countersignatureDelAttr = new CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA()
                {
                    dwSignerIndex     = 0,
                    dwUnauthAttrIndex = repositoryCountersignature.Value.dwUnauthAttrIndex
                };

                countersignatureDelAttr.cbSize = (uint)Marshal.SizeOf(countersignatureDelAttr);
                var unmanagedCountersignatureDelAttr = hb.Alloc(Marshal.SizeOf(countersignatureDelAttr));
                Marshal.StructureToPtr(countersignatureDelAttr, unmanagedCountersignatureDelAttr, fDeleteOld: false);

                if (!NativeMethods.CryptMsgControl(
                        _handle,
                        dwFlags: 0,
                        dwCtrlType: CMSG_CONTROL_TYPE.CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR,
                        pvCtrlPara: unmanagedCountersignatureDelAttr))
                {
                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                }

                // Add timestamp attribute to existing unsigned attributes
                var signerInfo      = repositoryCountersignature.Value.SignerInfo;
                var unauthAttrCount = signerInfo.UnauthAttrs.cAttr + 1;

                var sizeOfCryptAttribute = MarshalUtility.SizeOf <CRYPT_ATTRIBUTE>();
                var attributesArray      = (CRYPT_ATTRIBUTE *)hb.Alloc((int)(sizeOfCryptAttribute * unauthAttrCount));
                var currentAttribute     = attributesArray;

                // Copy existing unsigned attributes
                for (var i = 0; i < unauthAttrCount - 1; ++i)
                {
                    var existingAttributePointer = new IntPtr(
                        (long)signerInfo.UnauthAttrs.rgAttr + (i * sizeOfCryptAttribute));
                    var existingAttribute = MarshalUtility.PtrToStructure <CRYPT_ATTRIBUTE>(existingAttributePointer);

                    currentAttribute->pszObjId = existingAttribute.pszObjId;
                    currentAttribute->cValue   = existingAttribute.cValue;
                    currentAttribute->rgValue  = existingAttribute.rgValue;

                    currentAttribute++;
                }

                // Add timestamp attribute
                *currentAttribute = GetCryptAttributeForData(timestamp.Encode(), Oids.SignatureTimeStampTokenAttribute, hb);

                signerInfo.UnauthAttrs = new CRYPT_ATTRIBUTES()
                {
                    cAttr  = unauthAttrCount,
                    rgAttr = new IntPtr(attributesArray)
                };

                // Encode signer info
                var unmanagedSignerInfo = hb.Alloc(Marshal.SizeOf(signerInfo));
                Marshal.StructureToPtr(signerInfo, unmanagedSignerInfo, fDeleteOld: false);

                uint encodedLength = 0;
                if (!NativeMethods.CryptEncodeObjectEx(
                        CMSG_ENCODING.Any,
                        lpszStructType: new IntPtr(NativeMethods.PKCS7_SIGNER_INFO),
                        pvStructInfo: unmanagedSignerInfo,
                        dwFlags: 0,
                        pEncodePara: IntPtr.Zero,
                        pvEncoded: IntPtr.Zero,
                        pcbEncoded: ref encodedLength))
                {
                    var err = Marshal.GetLastWin32Error();
                    if (err != NativeMethods.ERROR_MORE_DATA)
                    {
                        Marshal.ThrowExceptionForHR(NativeMethods.GetHRForWin32Error(err));
                    }
                }

                var unmanagedEncoded = hb.Alloc((int)encodedLength);
                if (!NativeMethods.CryptEncodeObjectEx(
                        CMSG_ENCODING.Any,
                        lpszStructType: new IntPtr(NativeMethods.PKCS7_SIGNER_INFO),
                        pvStructInfo: unmanagedSignerInfo,
                        dwFlags: 0,
                        pEncodePara: IntPtr.Zero,
                        pvEncoded: unmanagedEncoded,
                        pcbEncoded: ref encodedLength))
                {
                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                }

                var encondedSignerBlob = new CRYPT_INTEGER_BLOB()
                {
                    cbData = encodedLength,
                    pbData = unmanagedEncoded
                };

                var unmanagedBlob = hb.Alloc(Marshal.SizeOf(encondedSignerBlob));
                Marshal.StructureToPtr(encondedSignerBlob, unmanagedBlob, fDeleteOld: false);

                var signerInfoAttr = new CRYPT_ATTRIBUTE()
                {
                    pszObjId = hb.AllocAsciiString(Oids.Countersignature),
                    cValue   = 1,
                    rgValue  = unmanagedBlob
                };

                // Create add unauth for signer info
                var signerInfoAddAttr = CreateUnsignedAddAttribute(signerInfoAttr, hb);

                // Add repository countersignature back to message
                signerInfoAddAttr.cbSize = (uint)Marshal.SizeOf(signerInfoAddAttr);
                var unmanagedSignerInfoAddAttr = hb.Alloc(Marshal.SizeOf(signerInfoAddAttr));

                Marshal.StructureToPtr(signerInfoAddAttr, unmanagedSignerInfoAddAttr, fDeleteOld: false);

                if (!NativeMethods.CryptMsgControl(
                        _handle,
                        dwFlags: 0,
                        dwCtrlType: CMSG_CONTROL_TYPE.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR,
                        pvCtrlPara: unmanagedSignerInfoAddAttr))
                {
                    Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
                }
            }
        }