internal void AddCertificates(IEnumerable <byte[]> encodedCertificates) { foreach (var cert in encodedCertificates) { using (var hb = new HeapBlockRetainer()) { var unmanagedCert = hb.Alloc(cert.Length); Marshal.Copy(cert, 0, unmanagedCert, cert.Length); var blob = new CRYPT_INTEGER_BLOB() { cbData = (uint)cert.Length, pbData = unmanagedCert }; var unmanagedBlob = hb.Alloc(Marshal.SizeOf(blob)); Marshal.StructureToPtr(blob, unmanagedBlob, fDeleteOld: false); if (!NativeMethods.CryptMsgControl( _handle, dwFlags: 0, dwCtrlType: CMSG_CONTROL_TYPE.CMSG_CTRL_ADD_CERT, pvCtrlPara: unmanagedBlob)) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } } } }
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); }
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()); } } }
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()); } } }