Beispiel #1
0
        private static bool IsRepositoryCounterSignerInfo(CRYPT_ATTRIBUTE_STRING commitmentTypeIndicationAttribute)
        {
            int sizeOfCryptIntegerBlob = MarshalUtility.SizeOf <CRYPT_INTEGER_BLOB>();

            for (var i = 0; i < commitmentTypeIndicationAttribute.cValue; ++i)
            {
                var attributeValuePointer = new IntPtr(
                    (long)commitmentTypeIndicationAttribute.rgValue + (i * sizeOfCryptIntegerBlob));
                var attributeValue = MarshalUtility.PtrToStructure <CRYPT_INTEGER_BLOB>(attributeValuePointer);
                var bytes          = new byte[attributeValue.cbData];

                Marshal.Copy(attributeValue.pbData, bytes, startIndex: 0, length: bytes.Length);

                var commitmentTypeIndication = CommitmentTypeIndication.Read(bytes);

                if (string.Equals(
                        commitmentTypeIndication.CommitmentTypeId.Value,
                        Oids.CommitmentTypeIdentifierProofOfReceipt,
                        StringComparison.Ordinal))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #2
0
        private static bool IsRepositoryCounterSignerInfo(CMSG_SIGNER_INFO counterSignerInfo)
        {
            var signedAttributes           = counterSignerInfo.AuthAttrs;
            int sizeOfCryptAttributeString = MarshalUtility.SizeOf <CRYPT_ATTRIBUTE_STRING>();

            for (var i = 0; i < signedAttributes.cAttr; ++i)
            {
                var signedAttributePointer = new IntPtr(
                    (long)signedAttributes.rgAttr + (i * sizeOfCryptAttributeString));
                var signedAttribute = MarshalUtility.PtrToStructure <CRYPT_ATTRIBUTE_STRING>(signedAttributePointer);
                if (string.Equals(signedAttribute.pszObjId, Oids.CommitmentTypeIndication, StringComparison.Ordinal) &&
                    IsRepositoryCounterSignerInfo(signedAttribute))
                {
                    return(true);
                }
            }

            return(false);
        }
Beispiel #3
0
        private unsafe RepositoryCounterSignerInfo?GetRepositoryCountersignature(HeapBlockRetainer retainer)
        {
            const uint primarySignerInfoIndex = 0;
            uint       unsignedAttributeCount = 0;
            var        pointer = IntPtr.Zero;

            NativeUtility.ThrowIfFailed(NativeMethods.CryptMsgGetParam(
                                            _handle,
                                            CMSG_GETPARAM_TYPE.CMSG_SIGNER_UNAUTH_ATTR_PARAM,
                                            primarySignerInfoIndex,
                                            pointer,
                                            ref unsignedAttributeCount));

            if (unsignedAttributeCount == 0)
            {
                return(null);
            }

            pointer = retainer.Alloc((int)unsignedAttributeCount);

            NativeUtility.ThrowIfFailed(NativeMethods.CryptMsgGetParam(
                                            _handle,
                                            CMSG_GETPARAM_TYPE.CMSG_SIGNER_UNAUTH_ATTR_PARAM,
                                            primarySignerInfoIndex,
                                            pointer,
                                            ref unsignedAttributeCount));

            var unsignedAttributes         = MarshalUtility.PtrToStructure <CRYPT_ATTRIBUTES>(pointer);
            int sizeOfCryptAttributeString = MarshalUtility.SizeOf <CRYPT_ATTRIBUTE_STRING>();
            int sizeOfCryptIntegerBlob     = MarshalUtility.SizeOf <CRYPT_INTEGER_BLOB>();

            for (uint i = 0; i < unsignedAttributes.cAttr; ++i)
            {
                var attributePointer = new IntPtr(
                    (long)unsignedAttributes.rgAttr + (i * sizeOfCryptAttributeString));
                var attribute = MarshalUtility.PtrToStructure <CRYPT_ATTRIBUTE_STRING>(attributePointer);

                if (!string.Equals(attribute.pszObjId, Oids.Countersignature, StringComparison.Ordinal))
                {
                    continue;
                }

                for (var j = 0; j < attribute.cValue; ++j)
                {
                    var attributeValuePointer = new IntPtr(
                        (long)attribute.rgValue + (j * sizeOfCryptIntegerBlob));
                    var  attributeValue = MarshalUtility.PtrToStructure <CRYPT_INTEGER_BLOB>(attributeValuePointer);
                    uint cbSignerInfo   = 0;

                    NativeUtility.ThrowIfFailed(NativeMethods.CryptDecodeObject(
                                                    CMSG_ENCODING.Any,
                                                    new IntPtr(NativeMethods.PKCS7_SIGNER_INFO),
                                                    attributeValue.pbData,
                                                    attributeValue.cbData,
                                                    dwFlags: 0,
                                                    pvStructInfo: IntPtr.Zero,
                                                    pcbStructInfo: new IntPtr(&cbSignerInfo)));

                    var counterSignerInfoPointer = retainer.Alloc((int)cbSignerInfo);

                    NativeUtility.ThrowIfFailed(NativeMethods.CryptDecodeObject(
                                                    CMSG_ENCODING.Any,
                                                    new IntPtr(NativeMethods.PKCS7_SIGNER_INFO),
                                                    attributeValue.pbData,
                                                    attributeValue.cbData,
                                                    dwFlags: 0,
                                                    pvStructInfo: counterSignerInfoPointer,
                                                    pcbStructInfo: new IntPtr(&cbSignerInfo)));

                    var counterSignerInfo = MarshalUtility.PtrToStructure <CMSG_SIGNER_INFO>(counterSignerInfoPointer);

                    if (IsRepositoryCounterSignerInfo(counterSignerInfo))
                    {
                        return(new RepositoryCounterSignerInfo()
                        {
                            dwUnauthAttrIndex = i,
                            UnauthAttr = attribute,
                            SignerInfo = counterSignerInfo
                        });
                    }
                }
            }

            return(null);
        }
Beispiel #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());
                }
            }
        }
Beispiel #5
0
        internal 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 = MarshalUtility.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
                {
                    int sizeOfCryptAttribute   = MarshalUtility.SizeOf <CRYPT_ATTRIBUTE>();
                    int sizeOfCryptIntegerBlob = MarshalUtility.SizeOf <CRYPT_INTEGER_BLOB>();
                    var attributesArray        = (CRYPT_ATTRIBUTE *)hb.Alloc(sizeOfCryptAttribute * 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(sizeOfCryptIntegerBlob);

                        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);
        }