private unsafe void RemoveCounterSignature(int parentIndex, int childIndex) { // Just make sure this is non-negative. if (parentIndex < 0) { throw new ArgumentOutOfRangeException("parentIndex"); } if (childIndex < 0) { throw new ArgumentOutOfRangeException("childIndex"); } uint cbCmsgCmsSignerInfo = 0; SafeLocalAllocHandle pbCmsgCmsSignerInfo = SafeLocalAllocHandle.InvalidHandle; uint cbCmsgSignerInfo = 0; SafeLocalAllocHandle pbCmsgSignerInfo = SafeLocalAllocHandle.InvalidHandle; uint index = 0; uint cAttr = 0; IntPtr pAttr = IntPtr.Zero; SafeCryptMsgHandle hMsg = m_signedCms.GetCryptMsgHandle(); if (PkcsUtils.CmsSupported()) { PkcsUtils.GetParam(hMsg, CAPI.CMSG_CMS_SIGNER_INFO_PARAM, (uint)parentIndex, out pbCmsgCmsSignerInfo, out cbCmsgCmsSignerInfo); CAPI.CMSG_CMS_SIGNER_INFO cmsgCmsSignerInfo = (CAPI.CMSG_CMS_SIGNER_INFO)Marshal.PtrToStructure(pbCmsgCmsSignerInfo.DangerousGetHandle(), typeof(CAPI.CMSG_CMS_SIGNER_INFO)); cAttr = cmsgCmsSignerInfo.UnauthAttrs.cAttr; pAttr = new IntPtr((long)cmsgCmsSignerInfo.UnauthAttrs.rgAttr); } else { PkcsUtils.GetParam(hMsg, CAPI.CMSG_SIGNER_INFO_PARAM, (uint)parentIndex, out pbCmsgSignerInfo, out cbCmsgSignerInfo); CAPI.CMSG_SIGNER_INFO cmsgSignerInfo = (CAPI.CMSG_SIGNER_INFO)Marshal.PtrToStructure(pbCmsgSignerInfo.DangerousGetHandle(), typeof(CAPI.CMSG_SIGNER_INFO)); cAttr = cmsgSignerInfo.UnauthAttrs.cAttr; pAttr = new IntPtr((long)cmsgSignerInfo.UnauthAttrs.rgAttr); } // Find index for counter signature attribute. // Note: It is not guaranteed that CAPI will keep all counter signatures // in one single unauthenticated attribute. So we need to find the correct // unauthenticated attribute containing this counter signer which is // identified by index. for (index = 0; index < cAttr; index++) { checked { CAPI.CRYPT_ATTRIBUTE attr = (CAPI.CRYPT_ATTRIBUTE)Marshal.PtrToStructure(pAttr, typeof(CAPI.CRYPT_ATTRIBUTE)); if (String.Compare(attr.pszObjId, CAPI.szOID_RSA_counterSign, StringComparison.OrdinalIgnoreCase) == 0) { if (attr.cValue > 0) { // Is it in this attribute? if (childIndex < (int)attr.cValue) { // Found the desired counter signature attribute. So, first remove the // entire attribute, then remove just the counter signature from the // retrieved attribute, and finally add back the modified attribute, // if necessary. CAPI.CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA delPara = new CAPI.CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA(Marshal.SizeOf(typeof(CAPI.CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA))); delPara.dwSignerIndex = (uint)parentIndex; delPara.dwUnauthAttrIndex = index; if (!CAPI.CryptMsgControl(hMsg, 0, CAPI.CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR, new IntPtr(&delPara))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } // No need to add back if only one counter signature in this attribute. if (attr.cValue > 1) { try { // There were more than one counter signatures in this attribute, so // need to add back a new counter signature attribute which includes // the remaining counter signatures. uint cbCounterSignatureValue = (uint)((attr.cValue - 1) * Marshal.SizeOf(typeof(CAPI.CRYPTOAPI_BLOB))); SafeLocalAllocHandle pbCounterSignatureValue = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(cbCounterSignatureValue)); // Copy everything except the one being removed. CAPI.CRYPTOAPI_BLOB *pOldValue = (CAPI.CRYPTOAPI_BLOB *)attr.rgValue; CAPI.CRYPTOAPI_BLOB *pNewValue = (CAPI.CRYPTOAPI_BLOB *)pbCounterSignatureValue.DangerousGetHandle(); for (int i = 0; i < (int)attr.cValue; i++, pOldValue++, pNewValue++) { if (i != childIndex) { *pNewValue = *pOldValue; } } // Encode the new counter signature attribute. byte[] encodedNewAttribute; CAPI.CRYPT_ATTRIBUTE newAttr = new CAPI.CRYPT_ATTRIBUTE(); newAttr.pszObjId = attr.pszObjId; newAttr.cValue = attr.cValue - 1; newAttr.rgValue = pbCounterSignatureValue.DangerousGetHandle(); SafeLocalAllocHandle pNewAttr = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CRYPT_ATTRIBUTE)))); Marshal.StructureToPtr(newAttr, pNewAttr.DangerousGetHandle(), false); try { if (!CAPI.EncodeObject(new IntPtr(CAPI.PKCS_ATTRIBUTE), pNewAttr.DangerousGetHandle(), out encodedNewAttribute)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } finally { Marshal.DestroyStructure(pNewAttr.DangerousGetHandle(), typeof(CAPI.CRYPT_ATTRIBUTE)); pNewAttr.Dispose(); } // Finally, add it back. fixed(byte *pbData = &encodedNewAttribute[0]) { CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA addPara = new CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA(Marshal.SizeOf(typeof(CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA))); addPara.dwSignerIndex = (uint)parentIndex; addPara.blob.cbData = (uint)encodedNewAttribute.Length; addPara.blob.pbData = new IntPtr(pbData); if (!CAPI.CryptMsgControl(hMsg, 0, CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR, new IntPtr(&addPara))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } // Keep alive. pbCounterSignatureValue.Dispose(); } catch (CryptographicException) { // Roll back. byte[] encodedAttribute; if (CAPI.EncodeObject(new IntPtr(CAPI.PKCS_ATTRIBUTE), pAttr, out encodedAttribute)) { fixed(byte *pbData = &encodedAttribute[0]) { CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA addPara = new CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA(Marshal.SizeOf(typeof(CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA))); addPara.dwSignerIndex = (uint)parentIndex; addPara.blob.cbData = (uint)encodedAttribute.Length; addPara.blob.pbData = new IntPtr(pbData); CAPI.CryptMsgControl(hMsg, 0, CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR, new IntPtr(&addPara)); } } throw; } } return; } childIndex -= (int)attr.cValue; } } pAttr = new IntPtr((long)pAttr + (long)Marshal.SizeOf(typeof(CAPI.CRYPT_ATTRIBUTE))); } } // Keep alive. if (pbCmsgCmsSignerInfo != null && !pbCmsgCmsSignerInfo.IsInvalid) { pbCmsgCmsSignerInfo.Dispose(); } if (pbCmsgSignerInfo != null && !pbCmsgSignerInfo.IsInvalid) { pbCmsgSignerInfo.Dispose(); } throw new CryptographicException(CAPI.CRYPT_E_NO_SIGNER); }
private unsafe void RemoveCounterSignature(int parentIndex, int childIndex) { if (parentIndex < 0) { throw new ArgumentOutOfRangeException("parentIndex"); } if (childIndex < 0) { throw new ArgumentOutOfRangeException("childIndex"); } uint cbData1 = 0U; SafeLocalAllocHandle pvData1 = SafeLocalAllocHandle.InvalidHandle; uint cbData2 = 0U; SafeLocalAllocHandle pvData2 = SafeLocalAllocHandle.InvalidHandle; IntPtr num1 = IntPtr.Zero; SafeCryptMsgHandle cryptMsgHandle = this.m_signedCms.GetCryptMsgHandle(); uint num2; if (PkcsUtils.CmsSupported()) { PkcsUtils.GetParam(cryptMsgHandle, 39U, (uint)parentIndex, out pvData1, out cbData1); CAPI.CMSG_CMS_SIGNER_INFO cmsgCmsSignerInfo = (CAPI.CMSG_CMS_SIGNER_INFO)Marshal.PtrToStructure(pvData1.DangerousGetHandle(), typeof(CAPI.CMSG_CMS_SIGNER_INFO)); num2 = cmsgCmsSignerInfo.UnauthAttrs.cAttr; num1 = new IntPtr((long)cmsgCmsSignerInfo.UnauthAttrs.rgAttr); } else { PkcsUtils.GetParam(cryptMsgHandle, 6U, (uint)parentIndex, out pvData2, out cbData2); CAPI.CMSG_SIGNER_INFO cmsgSignerInfo = (CAPI.CMSG_SIGNER_INFO)Marshal.PtrToStructure(pvData2.DangerousGetHandle(), typeof(CAPI.CMSG_SIGNER_INFO)); num2 = cmsgSignerInfo.UnauthAttrs.cAttr; num1 = new IntPtr((long)cmsgSignerInfo.UnauthAttrs.rgAttr); } for (uint index = 0U; index < num2; ++index) { CAPI.CRYPT_ATTRIBUTE cryptAttribute1 = (CAPI.CRYPT_ATTRIBUTE)Marshal.PtrToStructure(num1, typeof(CAPI.CRYPT_ATTRIBUTE)); if (string.Compare(cryptAttribute1.pszObjId, "1.2.840.113549.1.9.6", StringComparison.OrdinalIgnoreCase) == 0 && cryptAttribute1.cValue > 0U) { if (childIndex < (int)cryptAttribute1.cValue) { if (!CAPI.CryptMsgControl(cryptMsgHandle, 0U, 9U, new IntPtr((void *)&new CAPI.CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA(Marshal.SizeOf(typeof(CAPI.CMSG_CTRL_DEL_SIGNER_UNAUTH_ATTR_PARA))) { dwSignerIndex = (uint)parentIndex, dwUnauthAttrIndex = index }))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (cryptAttribute1.cValue <= 1U) { return; } try { SafeLocalAllocHandle localAllocHandle1 = CAPI.LocalAlloc(64U, new IntPtr((long)(uint)((ulong)(cryptAttribute1.cValue - 1U) * (ulong)Marshal.SizeOf(typeof(CAPI.CRYPTOAPI_BLOB))))); CAPI.CRYPTOAPI_BLOB *cryptoapiBlobPtr1 = (CAPI.CRYPTOAPI_BLOB *)(void *) cryptAttribute1.rgValue; CAPI.CRYPTOAPI_BLOB *cryptoapiBlobPtr2 = (CAPI.CRYPTOAPI_BLOB *)(void *) localAllocHandle1.DangerousGetHandle(); int num3 = 0; while (num3 < (int)cryptAttribute1.cValue) { if (num3 != childIndex) { *cryptoapiBlobPtr2 = *cryptoapiBlobPtr1; } ++num3; ++cryptoapiBlobPtr1; ++cryptoapiBlobPtr2; } CAPI.CRYPT_ATTRIBUTE cryptAttribute2 = new CAPI.CRYPT_ATTRIBUTE(); cryptAttribute2.pszObjId = cryptAttribute1.pszObjId; cryptAttribute2.cValue = cryptAttribute1.cValue - 1U; cryptAttribute2.rgValue = localAllocHandle1.DangerousGetHandle(); SafeLocalAllocHandle localAllocHandle2 = CAPI.LocalAlloc(64U, new IntPtr(Marshal.SizeOf(typeof(CAPI.CRYPT_ATTRIBUTE)))); Marshal.StructureToPtr((object)cryptAttribute2, localAllocHandle2.DangerousGetHandle(), false); byte[] encodedData; try { if (!CAPI.EncodeObject(new IntPtr(22L), localAllocHandle2.DangerousGetHandle(), out encodedData)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } finally { Marshal.DestroyStructure(localAllocHandle2.DangerousGetHandle(), typeof(CAPI.CRYPT_ATTRIBUTE)); localAllocHandle2.Dispose(); } fixed(byte *numPtr = &encodedData[0]) { if (!CAPI.CryptMsgControl(cryptMsgHandle, 0U, 8U, new IntPtr((void *)&new CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA(Marshal.SizeOf(typeof(CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA))) { dwSignerIndex = (uint)parentIndex, blob = { cbData = (uint)encodedData.Length, pbData = new IntPtr((void *)numPtr) } }))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } localAllocHandle1.Dispose(); return; } catch (CryptographicException ex) { byte[] encodedData; if (CAPI.EncodeObject(new IntPtr(22L), num1, out encodedData)) { fixed(byte *numPtr = &encodedData[0]) CAPI.CryptMsgControl(cryptMsgHandle, 0U, 8U, new IntPtr((void *)&new CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA(Marshal.SizeOf(typeof(CAPI.CMSG_CTRL_ADD_SIGNER_UNAUTH_ATTR_PARA))) { dwSignerIndex = (uint)parentIndex, blob = { cbData = (uint)encodedData.Length, pbData = new IntPtr((void *)numPtr) } })); } throw; } } else { childIndex -= (int)cryptAttribute1.cValue; } } num1 = new IntPtr((long)num1 + (long)Marshal.SizeOf(typeof(CAPI.CRYPT_ATTRIBUTE))); } if (pvData1 != null && !pvData1.IsInvalid) { pvData1.Dispose(); } if (pvData2 != null && !pvData2.IsInvalid) { pvData2.Dispose(); } throw new CryptographicException(-2146885618); }