Example #1
0
        private static void ProcessResponse(
            Rfc3161RequestResponseStatus expectedStatus,
            Rfc3161TimestampRequest request,
            byte[] inputBytes,
            int paddingByteCount)
        {
            Rfc3161TimestampToken token;
            int bytesRead;
            Rfc3161RequestResponseStatus status;
            bool result = request.TryProcessResponse(inputBytes, out token, out status, out bytesRead);

            Assert.Equal(expectedStatus, status);

            if (expectedStatus == Rfc3161RequestResponseStatus.Accepted)
            {
                Assert.True(result, "request.TryProcessResponse return value");
            }
            else
            {
                Assert.False(result, "request.TryProcessResponse return value");
            }

            if (expectedStatus == Rfc3161RequestResponseStatus.DoesNotParse)
            {
                Assert.Equal(0, bytesRead);
            }
            else
            {
                Assert.Equal(inputBytes.Length - paddingByteCount, bytesRead);
            }

            switch (expectedStatus)
            {
            case Rfc3161RequestResponseStatus.Accepted:
            case Rfc3161RequestResponseStatus.HashMismatch:
            case Rfc3161RequestResponseStatus.NonceMismatch:
            case Rfc3161RequestResponseStatus.UnexpectedCertificates:
            case Rfc3161RequestResponseStatus.RequestedCertificatesMissing:
            case Rfc3161RequestResponseStatus.VersionTooNew:
                Assert.NotNull(token);
                break;

            default:
                Assert.Null(token);
                break;
            }

            if (result)
            {
                Rfc3161TimestampToken token2 = request.ProcessResponse(inputBytes, out int bytesRead2);

                Assert.Equal(bytesRead, bytesRead2);
                Assert.NotNull(token2);
                Assert.NotSame(token, token2);
            }
            else
            {
                Assert.Throws <CryptographicException>(() => request.ProcessResponse(inputBytes, out bytesRead));
            }
        }
        public static void TryDecode_Fails_Empty()
        {
            Assert.False(
                Rfc3161TimestampToken.TryDecode(
                    ReadOnlyMemory <byte> .Empty,
                    out Rfc3161TimestampToken token,
                    out int bytesRead),
                "Rfc3161TimestampToken.TryDecode");

            Assert.Equal(0, bytesRead);
            Assert.Null(token);
        }
        public static void TryDecode_Fails_SignedCmsOfData()
        {
            Assert.False(
                Rfc3161TimestampToken.TryDecode(
                    SignedDocuments.RsaPkcs1OneSignerIssuerAndSerialNumber,
                    out Rfc3161TimestampToken token,
                    out int bytesRead),
                "Rfc3161TimestampToken.TryDecode");

            Assert.Equal(0, bytesRead);
            Assert.Null(token);
        }
Example #4
0
        internal static bool TryProcessResponse(
            this Rfc3161TimestampRequest request,
            ReadOnlyMemory <byte> inputBytes,
            out Rfc3161TimestampToken token,
            out TimestampRequestTests.Rfc3161RequestResponseStatus status,
            out int bytesRead)
        {
            object[] parameters = { inputBytes, null, null, null, false };
            object   result     = s_tryProcesses.Invoke(request, parameters);

            token = (Rfc3161TimestampToken)parameters[1];

            status = (TimestampRequestTests.Rfc3161RequestResponseStatus)
                     Enum.ToObject(typeof(TimestampRequestTests.Rfc3161RequestResponseStatus), parameters[2]);

            bytesRead = (int)parameters[3];

            return((bool)result);
        }
        public static void TryDecode_Fails_EnvelopedCms()
        {
            byte[] encodedMessage =
                ("3082010c06092a864886f70d010703a081fe3081fb0201003181c83081c5020100302e301a311830160603550403130f5253"
                 + "414b65795472616e7366657231021031d935fb63e8cfab48a0bf7b397b67c0300d06092a864886f70d010101050004818013"
                 + "dc0eb2984a445d04a1f6246b8fe41f1d24507548d449d454d5bb5e0638d75ed101bf78c0155a5d208eb746755fbccbc86923"
                 + "8443760a9ae94770d6373e0197be23a6a891f0c522ca96b3e8008bf23547474b7e24e7f32e8134df3862d84f4dea2470548e"
                 + "c774dd74f149a56cdd966e141122900d00ad9d10ea1848541294a1302b06092a864886f70d010701301406082a864886f70d"
                 + "030704089c8119f6cf6b174c8008bcea3a10d0737eb9").HexToByteArray();

            Assert.False(
                Rfc3161TimestampToken.TryDecode(
                    encodedMessage,
                    out Rfc3161TimestampToken token,
                    out int bytesRead),
                "Rfc3161TimestampToken.TryDecode");

            Assert.Equal(0, bytesRead);
            Assert.Null(token);
        }
        private static void CustomBuild_CertMatch(
            CertLoader loader,
            DateTimeOffset referenceTime,
            SigningCertificateOption v1Option,
            SigningCertificateOption v2Option,
            HashAlgorithmName v2AlgorithmName    = default,
            X509IncludeOption includeOption      = default,
            SubjectIdentifierType identifierType = SubjectIdentifierType.IssuerAndSerialNumber)
        {
            byte[] tokenBytes = BuildCustomToken(
                loader,
                referenceTime,
                v1Option,
                v2Option,
                v2AlgorithmName,
                includeOption,
                identifierType);

            Rfc3161TimestampToken token;

            Assert.True(Rfc3161TimestampToken.TryDecode(tokenBytes, out token, out int bytesRead));

            Assert.Equal(tokenBytes.Length, bytesRead);
            Assert.NotNull(token);

            Assert.Equal(referenceTime, token.TokenInfo.Timestamp);

            using (X509Certificate2 cert = Certificates.ValidLookingTsaCert.GetCertificate())
            {
                Assert.True(
                    token.VerifySignatureForHash(
                        token.TokenInfo.GetMessageHash().Span,
                        token.TokenInfo.HashAlgorithmId,
                        out X509Certificate2 signer,
                        new X509Certificate2Collection(cert)));

                Assert.Equal(cert, signer);
            }
        }
        public static void TryDecode_Fails_MalformedToken()
        {
            ContentInfo contentInfo = new ContentInfo(
                new Oid(Oids.TstInfo, Oids.TstInfo),
                new byte[] { 1 });

            SignedCms cms = new SignedCms(contentInfo);

            using (X509Certificate2 cert = Certificates.RSAKeyTransferCapi1.TryGetCertificateWithPrivateKey())
            {
                cms.ComputeSignature(new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert));
            }

            Assert.False(
                Rfc3161TimestampToken.TryDecode(
                    cms.Encode(),
                    out Rfc3161TimestampToken token,
                    out int bytesRead),
                "Rfc3161TimestampToken.TryDecode");

            Assert.Equal(0, bytesRead);
            Assert.Null(token);
        }
        private static void CustomBuild_CertMismatch(
            CertLoader loader,
            DateTimeOffset referenceTime,
            SigningCertificateOption v1Option,
            SigningCertificateOption v2Option,
            HashAlgorithmName v2AlgorithmName    = default,
            X509IncludeOption includeOption      = default,
            SubjectIdentifierType identifierType = SubjectIdentifierType.IssuerAndSerialNumber)
        {
            byte[] tokenBytes = BuildCustomToken(
                loader,
                referenceTime,
                v1Option,
                v2Option,
                v2AlgorithmName,
                includeOption,
                identifierType);

            Rfc3161TimestampToken token;

            bool willParse = includeOption == X509IncludeOption.None;

            if (willParse && identifierType == SubjectIdentifierType.IssuerAndSerialNumber)
            {
                // Because IASN matches against the ESSCertId(V2) directly it will reject the token.

                switch (v1Option)
                {
                case SigningCertificateOption.ValidHashWithInvalidName:
                case SigningCertificateOption.ValidHashWithInvalidSerial:
                case SigningCertificateOption.InvalidHashWithInvalidName:
                case SigningCertificateOption.InvalidHashWithInvalidSerial:
                    willParse = false;
                    break;
                }

                switch (v2Option)
                {
                case SigningCertificateOption.ValidHashWithInvalidName:
                case SigningCertificateOption.ValidHashWithInvalidSerial:
                case SigningCertificateOption.InvalidHashWithInvalidName:
                case SigningCertificateOption.InvalidHashWithInvalidSerial:
                    willParse = false;
                    break;
                }
            }

            if (willParse)
            {
                Assert.True(Rfc3161TimestampToken.TryDecode(tokenBytes, out token, out int bytesRead));
                Assert.NotNull(token);
                Assert.Equal(tokenBytes.Length, bytesRead);

                using (X509Certificate2 cert = loader.GetCertificate())
                {
                    Assert.False(
                        token.VerifySignatureForHash(
                            token.TokenInfo.GetMessageHash().Span,
                            token.TokenInfo.HashAlgorithmId,
                            out X509Certificate2 signer,
                            new X509Certificate2Collection(cert)));

                    Assert.Null(signer);
                }
            }
            else
            {
                Assert.False(Rfc3161TimestampToken.TryDecode(tokenBytes, out token, out int bytesRead));

                Assert.Null(token);
                Assert.Equal(0, bytesRead);
            }
        }
        private static void TestParseDocument(
            ReadOnlyMemory <byte> tokenBytes,
            TimestampTokenTestData testData,
            int?expectedBytesRead)
        {
            int bytesRead;
            Rfc3161TimestampToken token;

            Assert.True(
                Rfc3161TimestampToken.TryDecode(tokenBytes, out token, out bytesRead),
                "Rfc3161TimestampToken.TryDecode");

            if (expectedBytesRead != null)
            {
                Assert.Equal(expectedBytesRead.Value, bytesRead);
            }

            Assert.NotNull(token);
            TimestampTokenInfoTests.AssertEqual(testData, token.TokenInfo);

            SignedCms signedCms = token.AsSignedCms();

            Assert.NotNull(signedCms);
            Assert.Equal(Oids.TstInfo, signedCms.ContentInfo.ContentType.Value);

            Assert.Equal(
                testData.TokenInfoBytes.ByteArrayToHex(),
                signedCms.ContentInfo.Content.ByteArrayToHex());

            if (testData.EmbeddedSigningCertificate != null)
            {
                Assert.NotNull(signedCms.SignerInfos[0].Certificate);

                Assert.Equal(
                    testData.EmbeddedSigningCertificate.Value.ByteArrayToHex(),
                    signedCms.SignerInfos[0].Certificate.RawData.ByteArrayToHex());

                // Assert.NoThrow
                signedCms.CheckSignature(true);
            }
            else
            {
                Assert.Null(signedCms.SignerInfos[0].Certificate);

                using (var signerCert = new X509Certificate2(testData.ExternalCertificateBytes))
                {
                    // Assert.NoThrow
                    signedCms.CheckSignature(
                        new X509Certificate2Collection(signerCert),
                        true);
                }
            }

            X509Certificate2           returnedCert;
            ReadOnlySpan <byte>        messageContentSpan = testData.MessageContent.Span;
            X509Certificate2Collection candidates         = null;

            if (testData.EmbeddedSigningCertificate != null)
            {
                Assert.True(
                    token.VerifySignatureForData(messageContentSpan, out returnedCert),
                    "token.VerifySignatureForData(correct)");

                Assert.NotNull(returnedCert);
                Assert.Equal(signedCms.SignerInfos[0].Certificate, returnedCert);
            }
            else
            {
                candidates = new X509Certificate2Collection
                {
                    new X509Certificate2(testData.ExternalCertificateBytes),
                };

                Assert.False(
                    token.VerifySignatureForData(messageContentSpan, out returnedCert),
                    "token.VerifySignatureForData(correct, no cert)");

                Assert.Null(returnedCert);

                Assert.True(
                    token.VerifySignatureForData(messageContentSpan, out returnedCert, candidates),
                    "token.VerifySignatureForData(correct, certs)");

                Assert.NotNull(returnedCert);
                Assert.Equal(candidates[0], returnedCert);
            }

            X509Certificate2 previousCert = returnedCert;

            Assert.False(
                token.VerifySignatureForData(messageContentSpan.Slice(1), out returnedCert, candidates),
                "token.VerifySignatureForData(incorrect)");

            Assert.Null(returnedCert);

            byte[] messageHash = testData.HashBytes.ToArray();

            Assert.False(
                token.VerifySignatureForHash(messageHash, HashAlgorithmName.MD5, out returnedCert, candidates),
                "token.VerifyHash(correct, MD5)");
            Assert.Null(returnedCert);

            Assert.False(
                token.VerifySignatureForHash(messageHash, new Oid(Oids.Md5), out returnedCert, candidates),
                "token.VerifyHash(correct, Oid(MD5))");
            Assert.Null(returnedCert);

            Assert.True(
                token.VerifySignatureForHash(messageHash, new Oid(testData.HashAlgorithmId), out returnedCert, candidates),
                "token.VerifyHash(correct, Oid(algId))");
            Assert.NotNull(returnedCert);
            Assert.Equal(previousCert, returnedCert);

            messageHash[0] ^= 0xFF;
            Assert.False(
                token.VerifySignatureForHash(messageHash, new Oid(testData.HashAlgorithmId), out returnedCert, candidates),
                "token.VerifyHash(incorrect, Oid(algId))");
            Assert.Null(returnedCert);
        }
Example #10
0
        internal static bool?CheckRFC3161TimestampInternal(SignerInfo signerInfo, DateTimeOffset?notBefore, DateTimeOffset?notAfter)
        {
            bool found = false;

            byte[] signatureBytes = null;

            foreach (CryptographicAttributeObject attr in signerInfo.UnsignedAttributes)
            {
                if (attr.Oid.Value == CertificateHelper.SignatureTimeStampOin.Value)
                {
                    foreach (AsnEncodedData attrInst in attr.Values)
                    {
                        byte[] attrData = attrInst.RawData;

                        // New API starts here:
                        if (!Rfc3161TimestampToken.TryDecode(attrData, out var token, out var bytesRead))
                        {
                            return(false);
                        }

                        if (bytesRead != attrData.Length)
                        {
                            return(false);
                        }

                        signatureBytes = signatureBytes ?? signerInfo.GetSignature();

                        // Check that the token was issued based on the SignerInfo's signature value
                        if (!token.VerifySignatureForSignerInfo(signerInfo, out _))
                        {
                            return(false);
                        }

                        var timestamp = token.TokenInfo.Timestamp;

                        // Check that the signed timestamp is within the provided policy range
                        // (which may be (signerInfo.Certificate.NotBefore, signerInfo.Certificate.NotAfter);
                        // or some other policy decision)
                        if (timestamp < notBefore.GetValueOrDefault(timestamp) ||
                            timestamp > notAfter.GetValueOrDefault(timestamp))
                        {
                            return(false);
                        }

                        var tokenSignerCert = token.AsSignedCms().SignerInfos[0].Certificate;

                        // Implicit policy decision: Tokens required embedded certificates (since this method has
                        // no resolver)
                        if (tokenSignerCert == null)
                        {
                            return(false);
                        }

                        found = true;
                    }
                }
            }

            // If we found any attributes and none of them returned an early false, then the SignerInfo is
            // conformant to policy.
            if (found)
            {
                return(true);
            }

            // Inconclusive, as no signed timestamps were found
            return(null);
        }