/// <summary>
        /// Load content from a stream.
        /// </summary>
        private static SignatureContent Load(Stream stream, SigningSpecifications signingSpecifications)
        {
            var    hashAlgorithm = HashAlgorithmName.Unknown;
            string hash          = null;

            using (var reader = new KeyPairFileReader(stream, signingSpecifications.Encoding))
            {
                // Read header-section.
                var properties = reader.ReadSection();

                ThrowIfEmpty(properties);
                ThrowIfSignatureFormatVersionIsUnsupported(properties, signingSpecifications);

                // Read only the first section.
                properties = reader.ReadSection();

                ThrowIfEmpty(properties);

                foreach (var property in properties)
                {
                    if (TryReadPackageHashProperty(property, signingSpecifications, out hashAlgorithm))
                    {
                        hash = property.Value;
                        break;
                    }
                }

                if (string.IsNullOrEmpty(hash))
                {
                    throw new SignatureException(Strings.UnableToReadPackageHashInformation);
                }
            }

            return(new SignatureContent(signingSpecifications, hashAlgorithm, hash));
        }
 internal static IReadOnlyList <X509Certificate2> GetPrimarySignatureCertificates(
     SignedCms signedCms,
     SignerInfo signerInfo,
     SigningSpecifications signingSpecifications)
 {
     return(GetPrimarySignatureCertificates(signedCms, signerInfo, signingSpecifications, includeChain: false));
 }
        private static IX509CertificateChain GetTimestampCertificates(
            SignedCms signedCms,
            SigningSpecifications signingSpecifications,
            string signatureFriendlyName,
            bool includeChain)
        {
            var errors = new Errors(
                noCertificate: NuGetLogCode.NU3020,
                noCertificateString: string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampNoCertificate, signatureFriendlyName),
                invalidSignature: NuGetLogCode.NU3021,
                invalidSignatureString: string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampInvalid, signatureFriendlyName),
                chainBuildingFailed: NuGetLogCode.NU3028);

            if (signedCms.SignerInfos.Count != 1)
            {
                throw new SignatureException(errors.InvalidSignature, errors.InvalidSignatureString);
            }

            const bool isIssuerSerialRequired = false;

            return(GetCertificates(
                       signedCms,
                       signedCms.SignerInfos[0],
                       SigningCertificateRequirement.EitherOrBoth,
                       isIssuerSerialRequired,
                       errors,
                       signingSpecifications,
                       includeChain));
        }
        private static IX509CertificateChain GetRepositoryCountersignatureCertificates(
            SignedCms signedCms,
            SignerInfo signerInfo,
            SigningSpecifications signingSpecifications,
            bool includeChain)
        {
            if (signedCms == null)
            {
                throw new ArgumentNullException(nameof(signedCms));
            }

            if (signerInfo == null)
            {
                throw new ArgumentNullException(nameof(signerInfo));
            }

            var errors = new Errors(
                noCertificate: NuGetLogCode.NU3034,
                noCertificateString: Strings.RepositoryCountersignatureHasNoCertificate,
                invalidSignature: NuGetLogCode.NU3031,
                invalidSignatureString: Strings.InvalidRepositoryCountersignature,
                chainBuildingFailed: NuGetLogCode.NU3035);

            var isIssuerSerialRequired = true;

            return(GetCertificates(
                       signedCms,
                       signerInfo,
                       SigningCertificateRequirement.OnlyV2,
                       isIssuerSerialRequired,
                       errors,
                       signingSpecifications,
                       includeChain));
        }
Beispiel #5
0
 private static void VerifyAuthorSignatureRequirements(
     SignerInfo signerInfo,
     SigningSpecifications signingSpecifications)
 {
     VerifySigningCertificateV2Attribute(signerInfo, signingSpecifications);
     VerifySigningTimeAttribute(signerInfo);
 }
        internal static IReadOnlyList <X509Certificate2> GetTimestampCertificates(
            SignedCms signedCms,
            SigningSpecifications signingSpecifications,
            bool includeChain)
        {
            var errors = new Errors(
                noCertificate: NuGetLogCode.NU3020,
                noCertificateString: Strings.TimestampNoCertificate,
                invalidSignature: NuGetLogCode.NU3021,
                invalidSignatureString: Strings.TimestampInvalid,
                chainBuildingFailed: NuGetLogCode.NU3028);

            if (signedCms.SignerInfos.Count != 1)
            {
                throw new SignatureException(errors.InvalidSignature, errors.InvalidSignatureString);
            }

            const bool isIssuerSerialRequired = false;

            return(GetCertificates(
                       signedCms,
                       signedCms.SignerInfos[0],
                       SigningCertificateRequirement.EitherOrBoth,
                       isIssuerSerialRequired,
                       errors,
                       signingSpecifications,
                       includeChain));
        }
        private static void ValidateTimestampCms(SigningSpecifications spec, SignedCms timestampCms)
        {
            var signerInfo = timestampCms.SignerInfos[0];

            try
            {
                signerInfo.CheckSignature(verifySignatureOnly: true);
            }
            catch (Exception e)
            {
                throw new TimestampException(NuGetLogCode.NU3021, Strings.TimestampSignatureValidationFailed, e);
            }

            if (!CertificateUtility.IsSignatureAlgorithmSupported(signerInfo.Certificate))
            {
                throw new TimestampException(NuGetLogCode.NU3022, Strings.TimestampUnsupportedSignatureAlgorithm);
            }

            if (!CertificateUtility.IsCertificatePublicKeyValid(signerInfo.Certificate))
            {
                throw new TimestampException(NuGetLogCode.NU3023, Strings.TimestampCertificateFailsPublicKeyLengthRequirement);
            }

            if (!spec.AllowedHashAlgorithmOids.Contains(signerInfo.DigestAlgorithm.Value))
            {
                throw new TimestampException(NuGetLogCode.NU3024, Strings.TimestampUnsupportedSignatureAlgorithm);
            }

            if (CertificateUtility.IsCertificateValidityPeriodInTheFuture(signerInfo.Certificate))
            {
                throw new TimestampException(NuGetLogCode.NU3025, Strings.TimestampNotYetValid);
            }
        }
 public TimestampRequest(SigningSpecifications signingSpecifications, byte[] hashedMessage, HashAlgorithmName hashAlgorithm, SignaturePlacement target)
 {
     SigningSpecifications = signingSpecifications ?? throw new ArgumentNullException(nameof(signingSpecifications));
     HashedMessage         = hashedMessage ?? throw new ArgumentNullException(nameof(hashedMessage));
     HashAlgorithm         = hashAlgorithm;
     Target = target;
 }
 internal static IX509CertificateChain GetCertificateChain(
     SignedCms signedCms,
     SignerInfo signerInfo,
     SigningSpecifications signingSpecifications,
     string signatureFriendlyName)
 {
     return(GetPrimarySignatureCertificates(signedCms, signerInfo, signingSpecifications, signatureFriendlyName, includeChain: false));
 }
 internal static IReadOnlyList <X509Certificate2> GetTimestampCertificates(
     SignedCms signedCms,
     SigningSpecifications signingSpecifications)
 {
     return(GetTimestampCertificates(
                signedCms,
                signingSpecifications,
                includeChain: false));
 }
 internal static IX509CertificateChain GetTimestampCertificates(
     SignedCms signedCms,
     SigningSpecifications signingSpecifications,
     string signatureFriendlyName)
 {
     return(GetTimestampCertificates(
                signedCms,
                signingSpecifications,
                signatureFriendlyName,
                includeChain: false));
 }
Beispiel #12
0
 /// <summary>
 /// Verify a signing-certificate-v2 attribute.
 /// </summary>
 public static bool IsValidSigningCertificateV2(
     X509Certificate2 signatureCertificate,
     IReadOnlyList <X509Certificate2> chain,
     CryptographicAttributeObject signingCertV2Attribute,
     SigningSpecifications signingSpecifications)
 {
     return(IsValidSigningCertificateV2(
                signatureCertificate: signatureCertificate,
                localCertificateChain: chain,
                attributeCertificateChain: GetESSCertIDv2Entries(signingCertV2Attribute),
                signingSpecifications: signingSpecifications));
 }
Beispiel #13
0
 /// <summary>
 /// Verify a signing-certificate-v2 attribute.
 /// </summary>
 public static bool IsValidSigningCertificateV2(
     X509Certificate2 signatureCertificate,
     X509Chain chain,
     CryptographicAttributeObject signingCertV2Attribute,
     SigningSpecifications signingSpecifications)
 {
     return(IsValidSigningCertificateV2(
                signatureCertificate: signatureCertificate,
                chain: SigningUtility.GetCertificateChain(chain),
                signingCertV2Attribute: signingCertV2Attribute,
                signingSpecifications: signingSpecifications));
 }
        private static IX509CertificateChain GetPrimarySignatureCertificates(
            SignedCms signedCms,
            SignerInfo signerInfo,
            SigningSpecifications signingSpecifications,
            string signatureFriendlyName,
            bool includeChain)
        {
            if (signedCms == null)
            {
                throw new ArgumentNullException(nameof(signedCms));
            }

            if (signerInfo == null)
            {
                throw new ArgumentNullException(nameof(signerInfo));
            }

            var errors = new Errors(
                noCertificate: NuGetLogCode.NU3010,
                noCertificateString: string.Format(CultureInfo.CurrentCulture, Strings.Verify_ErrorNoCertificate, signatureFriendlyName),
                invalidSignature: NuGetLogCode.NU3011,
                invalidSignatureString: Strings.InvalidPrimarySignature,
                chainBuildingFailed: NuGetLogCode.NU3018);

            var signatureType = AttributeUtility.GetSignatureType(signerInfo.SignedAttributes);
            SigningCertificateRequirement signingCertificateRequirement;
            bool isIssuerSerialRequired;

            switch (signatureType)
            {
            case SignatureType.Author:
            case SignatureType.Repository:
                signingCertificateRequirement = SigningCertificateRequirement.OnlyV2;
                isIssuerSerialRequired        = true;
                break;

            default:
                signingCertificateRequirement = SigningCertificateRequirement.NoRequirement;
                isIssuerSerialRequired        = false;
                break;
            }

            return(GetCertificates(
                       signedCms,
                       signerInfo,
                       signingCertificateRequirement,
                       isIssuerSerialRequired,
                       errors,
                       signingSpecifications,
                       includeChain));
        }
Beispiel #15
0
        /// <summary>
        /// Verify components of a signing-certificate-v2 attribute.
        /// </summary>
        public static bool IsValidSigningCertificateV2(
            X509Certificate2 signatureCertificate,
            IReadOnlyList <X509Certificate2> localCertificateChain,
            IReadOnlyList <KeyValuePair <Common.HashAlgorithmName, byte[]> > attributeCertificateChain,
            SigningSpecifications signingSpecifications)
        {
            // Verify chain counts to avoid unneeded hashing
            if (localCertificateChain.Count != attributeCertificateChain.Count || attributeCertificateChain.Count < 1)
            {
                return(false);
            }

            // Check each entry in the chain
            for (var i = 0; i < attributeCertificateChain.Count; i++)
            {
                var attributeEntry = attributeCertificateChain[i];
                var localEntry     = localCertificateChain[i];

                // Verify hash algorithm is allowed
                if (!signingSpecifications.AllowedHashAlgorithmOids.Contains(
                        attributeEntry.Key.ConvertToOidString(),
                        StringComparer.Ordinal))
                {
                    return(false);
                }

                // Hash the local cert using the attribute hash algorithm
                var localValue = GetESSCertIDv2Entry(localEntry, attributeEntry.Key);

                // Verify the hashes match
                if (!VerifyHash(localValue, attributeEntry))
                {
                    return(false);
                }

                // Verify the first entry is the leaf cert used
                if (i == 0)
                {
                    var leafHash = GetESSCertIDv2Entry(signatureCertificate, attributeEntry.Key);

                    if (!VerifyHash(leafHash, attributeEntry))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Beispiel #16
0
        private static void VerifySigningCertificate(
            SignedCms signedCms,
            SignerInfo signerInfo,
            SigningSpecifications signingSpecifications)
        {
            var certificates = SignatureUtility.GetPrimarySignatureCertificates(
                signedCms,
                signerInfo,
                signingSpecifications);

            if (certificates == null || certificates.Count == 0)
            {
                ThrowForInvalidPrimarySignature();
            }
        }
Beispiel #17
0
 private static void VerifySigningCertificate(
     SignedCms signedCms,
     SignerInfo signerInfo,
     SigningSpecifications signingSpecifications)
 {
     using (var certificates = SignatureUtility.GetCertificateChain(
                signedCms,
                signerInfo,
                signingSpecifications,
                Strings.PrimarySignatureFriendlyName))
     {
         if (certificates == null || certificates.Count == 0)
         {
             ThrowForInvalidPrimarySignature();
         }
     }
 }
Beispiel #18
0
        /// <summary>
        /// Load from a byte array.
        /// </summary>
        public static SignatureContent Load(byte[] bytes, SigningSpecifications signingSpecifications)
        {
            if (bytes == null)
            {
                throw new ArgumentNullException(nameof(bytes));
            }

            if (signingSpecifications == null)
            {
                throw new ArgumentNullException(nameof(signingSpecifications));
            }

            using (var ms = new MemoryStream(bytes))
            {
                ms.Position = 0;
                return(Load(ms, signingSpecifications));
            }
        }
Beispiel #19
0
        public SignatureContent(
            SigningSpecifications signingSpecifications,
            HashAlgorithmName hashAlgorithm,
            string hashValue)
        {
            if (signingSpecifications == null)
            {
                throw new ArgumentNullException(nameof(signingSpecifications));
            }

            if (string.IsNullOrEmpty(hashValue))
            {
                throw new ArgumentException(Strings.StringCannotBeNullOrEmpty, nameof(hashValue));
            }

            _signingSpecifications = signingSpecifications;
            HashAlgorithm          = hashAlgorithm;
            HashValue = hashValue;
        }
Beispiel #20
0
        private static void VerifySigningCertificateV2Attribute(
            SignerInfo signerInfo,
            SigningSpecifications signingSpecifications)
        {
            var attribute = signerInfo.SignedAttributes.GetAttributeOrDefault(Oids.SigningCertificateV2);

            if (attribute != null)
            {
                var entries = AttributeUtility.GetESSCertIDv2Entries(attribute);

                if (entries != null && entries.Count > 0)
                {
                    if (entries.All(
                            kvp => signingSpecifications.AllowedHashAlgorithmOids.Contains(kvp.Key.ConvertToOidString())))
                    {
                        return;
                    }
                }
            }

            ThrowForInvalidAuthorSignature();
        }
Beispiel #21
0
        private static bool TryReadPackageHashProperty(
            KeyValuePair <string, string> property,
            SigningSpecifications signingSpecifications,
            out HashAlgorithmName hashAlgorithmName)
        {
            hashAlgorithmName = HashAlgorithmName.Unknown;

            if (property.Key.EndsWith("-Hash", StringComparison.Ordinal))
            {
                foreach (var hashAlgorithmOid in signingSpecifications.AllowedHashAlgorithmOids)
                {
                    if (property.Key == $"{hashAlgorithmOid}-Hash")
                    {
                        hashAlgorithmName = CryptoHashUtility.OidToHashAlgorithmName(hashAlgorithmOid);

                        return(true);
                    }
                }
            }

            return(false);
        }
        private static void ValidateTimestampCms(SigningSpecifications spec, SignedCms timestampCms, IRfc3161TimestampToken timestampToken)
        {
            var signerInfo = timestampCms.SignerInfos[0];

            try
            {
                signerInfo.CheckSignature(verifySignatureOnly: true);
            }
            catch (Exception e)
            {
                throw new TimestampException(NuGetLogCode.NU3021, Strings.SignError_TimestampSignatureValidationFailed, e);
            }

            if (signerInfo.Certificate == null)
            {
                throw new TimestampException(NuGetLogCode.NU3020, Strings.SignError_TimestampNoCertificate);
            }

            if (!CertificateUtility.IsSignatureAlgorithmSupported(signerInfo.Certificate))
            {
                var certificateSignatureAlgorithm = GetNameOrOidString(signerInfo.Certificate.SignatureAlgorithm);

                var supportedSignatureAlgorithms = string.Join(", ", spec.AllowedSignatureAlgorithms);

                var errorMessage = string.Format(CultureInfo.CurrentCulture,
                                                 Strings.TimestampCertificateUnsupportedSignatureAlgorithm,
                                                 certificateSignatureAlgorithm,
                                                 supportedSignatureAlgorithms);

                throw new TimestampException(NuGetLogCode.NU3022, errorMessage);
            }

            if (!CertificateUtility.IsCertificatePublicKeyValid(signerInfo.Certificate))
            {
                throw new TimestampException(NuGetLogCode.NU3023, Strings.SignError_TimestampCertificateFailsPublicKeyLengthRequirement);
            }

            if (!spec.AllowedHashAlgorithmOids.Contains(signerInfo.DigestAlgorithm.Value))
            {
                var digestAlgorithm = GetNameOrOidString(signerInfo.DigestAlgorithm);

                var supportedSignatureAlgorithms = string.Join(", ", spec.AllowedHashAlgorithms);

                var errorMessage = string.Format(CultureInfo.CurrentCulture,
                                                 Strings.TimestampSignatureUnsupportedDigestAlgorithm,
                                                 digestAlgorithm,
                                                 supportedSignatureAlgorithms);

                throw new TimestampException(NuGetLogCode.NU3024, errorMessage);
            }

            if (CertificateUtility.IsCertificateValidityPeriodInTheFuture(signerInfo.Certificate))
            {
                throw new TimestampException(NuGetLogCode.NU3025, Strings.SignError_TimestampNotYetValid);
            }

            if (!CertificateUtility.IsDateInsideValidityPeriod(signerInfo.Certificate, timestampToken.TokenInfo.Timestamp))
            {
                throw new TimestampException(NuGetLogCode.NU3036, Strings.SignError_TimestampGeneralizedTimeInvalid);
            }
        }
Beispiel #23
0
        internal static bool IsTimestampValid(Timestamp timestamp, byte[] data, bool treatIssuesAsErrors, List <SignatureLog> issues, SigningSpecifications spec)
        {
            var isValid    = true;
            var signerInfo = timestamp.SignerInfo;

            if (!timestamp.TstInfo.HasMessageHash(data))
            {
                issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3019, Strings.TimestampIntegrityCheckFailed));
                isValid = false;
            }

            if (timestamp.SignerInfo.Certificate != null)
            {
                try
                {
                    signerInfo.CheckSignature(verifySignatureOnly: true);
                }
                catch (Exception e)
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3021, Strings.TimestampSignatureValidationFailed));
                    issues.Add(SignatureLog.DebugLog(e.ToString()));
                    isValid = false;
                }

                if (!CertificateUtility.IsSignatureAlgorithmSupported(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3022, Strings.TimestampUnsupportedSignatureAlgorithm));
                    isValid = false;
                }

                if (!CertificateUtility.IsCertificatePublicKeyValid(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3023, Strings.TimestampCertificateFailsPublicKeyLengthRequirement));
                    isValid = false;
                }

                if (!spec.AllowedHashAlgorithmOids.Contains(signerInfo.DigestAlgorithm.Value))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3024, Strings.TimestampUnsupportedSignatureAlgorithm));
                    isValid = false;
                }

                if (CertificateUtility.IsCertificateValidityPeriodInTheFuture(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3025, Strings.TimestampNotYetValid));
                    isValid = false;
                }
            }
            else
            {
                issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3020, Strings.TimestampNoCertificate));
                isValid = false;
            }

            return(isValid);
        }
Beispiel #24
0
        private static void ThrowIfSignatureFormatVersionIsUnsupported(Dictionary <string, string> properties, SigningSpecifications signingSpecifications)
        {
            const string Version = "Version";

            string signatureFormatVersion;

            if (!properties.TryGetValue(Version, out signatureFormatVersion))
            {
                throw new SignatureException(Strings.InvalidSignatureContent);
            }

            if (signingSpecifications.Version != signatureFormatVersion)
            {
                throw new SignatureException(NuGetLogCode.NU3007, Strings.UnsupportedSignatureFormatVersion);
            }
        }
        private static IX509CertificateChain GetCertificates(
            SignedCms signedCms,
            SignerInfo signerInfo,
            SigningCertificateRequirement signingCertificateRequirement,
            bool isIssuerSerialRequired,
            Errors errors,
            SigningSpecifications signingSpecifications,
            bool includeChain)
        {
            if (signedCms == null)
            {
                throw new ArgumentNullException(nameof(signedCms));
            }

            if (signingSpecifications == null)
            {
                throw new ArgumentNullException(nameof(signingSpecifications));
            }

            if (signerInfo.Certificate == null)
            {
                throw new SignatureException(errors.NoCertificate, errors.NoCertificateString);
            }

            /*
             *  The signing-certificate and signing-certificate-v2 attributes are described in RFC 2634 and RFC 5035.
             *
             *  Timestamps
             *  --------------------------------------------------
             *  RFC 3161 requires the signing-certificate attribute.  The RFC 5816 update introduces the newer
             *  signing-certificate-v2 attribute, which may replace or, for backwards compatibility, be present
             *  alongside the older signing-certificate attribute.
             *
             *  The issuerSerial field is not required, but should be validated if present.
             *
             *
             *  Author and repository signatures
             *  --------------------------------------------------
             *  RFC 5126 (CAdES) requires that exactly one of either of these attributes be present, and also requires that
             *  the issuerSerial field be present.
             *
             *
             *  Validation
             *  --------------------------------------------------
             *  For author and repository signatures:
             *
             * the signing-certificate attribute must not be present
             * the signing-certificate-v2 attribute be present
             * the issuerSerial field must be present
             *
             *
             *  References:
             *
             *      "Signing Certificate Attribute Definition", RFC 2634 section 5.4 (https://tools.ietf.org/html/rfc2634#section-5.4)
             *      "Certificate Identification", RFC 2634 section 5.4 (https://tools.ietf.org/html/rfc2634#section-5.4.1)
             *      "Enhanced Security Services (ESS) Update: Adding CertID Algorithm Agility", RFC 5035 (https://tools.ietf.org/html/rfc5035)
             *      "Request Format", RFC 3161 section 2.4.1 (https://tools.ietf.org/html/rfc3161#section-2.4.1)
             *      "Signature of Time-Stamp Token", RFC 5816 section 2.2.1 (https://tools.ietf.org/html/rfc5816#section-2.2.1)
             *      "Signing Certificate Reference Attributes", RFC 5126 section 5.7.3 (https://tools.ietf.org/html/rfc5126.html#section-5.7.3)
             *      "ESS signing-certificate Attribute Definition", RFC 5126 section 5.7.3.1 (https://tools.ietf.org/html/rfc5126.html#section-5.7.3.1)
             *      "ESS signing-certificate-v2 Attribute Definition", RFC 5126 section 5.7.3.2 (https://tools.ietf.org/html/rfc5126.html#section-5.7.3.2)
             */

            const string signingCertificateName   = "signing-certificate";
            const string signingCertificateV2Name = "signing-certificate-v2";

            CryptographicAttributeObject signingCertificateAttribute   = null;
            CryptographicAttributeObject signingCertificateV2Attribute = null;

            foreach (var attribute in signerInfo.SignedAttributes)
            {
                switch (attribute.Oid.Value)
                {
                case Oids.SigningCertificate:
                    if (signingCertificateAttribute != null)
                    {
                        throw new SignatureException(
                                  errors.InvalidSignature,
                                  string.Format(
                                      CultureInfo.CurrentCulture,
                                      Strings.MultipleAttributesDisallowed,
                                      signingCertificateName));
                    }

                    if (attribute.Values.Count != 1)
                    {
                        throw new SignatureException(
                                  errors.InvalidSignature,
                                  string.Format(
                                      CultureInfo.CurrentCulture,
                                      Strings.ExactlyOneAttributeValueRequired,
                                      signingCertificateName));
                    }

                    signingCertificateAttribute = attribute;
                    break;

                case Oids.SigningCertificateV2:
                    if (signingCertificateV2Attribute != null)
                    {
                        throw new SignatureException(
                                  errors.InvalidSignature,
                                  string.Format(
                                      CultureInfo.CurrentCulture,
                                      Strings.MultipleAttributesDisallowed,
                                      signingCertificateV2Name));
                    }

                    if (attribute.Values.Count != 1)
                    {
                        throw new SignatureException(
                                  errors.InvalidSignature,
                                  string.Format(
                                      CultureInfo.CurrentCulture,
                                      Strings.ExactlyOneAttributeValueRequired,
                                      signingCertificateV2Name));
                    }

                    signingCertificateV2Attribute = attribute;
                    break;
                }
            }

            switch (signingCertificateRequirement)
            {
            case SigningCertificateRequirement.OnlyV2:
            {
                if (signingCertificateAttribute != null)
                {
                    throw new SignatureException(errors.InvalidSignature, Strings.SigningCertificateAttributeMustNotBePresent);
                }

                if (signingCertificateV2Attribute == null)
                {
                    throw new SignatureException(
                              errors.InvalidSignature,
                              string.Format(CultureInfo.CurrentCulture,
                                            Strings.ExactlyOneAttributeRequired,
                                            signingCertificateV2Name));
                }
            }
            break;

            case SigningCertificateRequirement.EitherOrBoth:
                if (signingCertificateAttribute == null && signingCertificateV2Attribute == null)
                {
                    throw new SignatureException(errors.InvalidSignature, Strings.SigningCertificateV1OrV2AttributeMustBePresent);
                }
                break;
            }

            if (signingCertificateV2Attribute != null)
            {
                var reader = CreateDerSequenceReader(signingCertificateV2Attribute);
                var signingCertificateV2 = SigningCertificateV2.Read(reader);

                if (signingCertificateV2.Certificates.Count == 0)
                {
                    throw new SignatureException(errors.InvalidSignature, Strings.SigningCertificateV2Invalid);
                }

                foreach (var essCertIdV2 in signingCertificateV2.Certificates)
                {
                    if (!signingSpecifications.AllowedHashAlgorithmOids.Contains(
                            essCertIdV2.HashAlgorithm.Algorithm.Value,
                            StringComparer.Ordinal))
                    {
                        throw new SignatureException(errors.InvalidSignature, Strings.SigningCertificateV2UnsupportedHashAlgorithm);
                    }
                }

                if (!IsMatch(signerInfo.Certificate, signingCertificateV2.Certificates[0], errors, isIssuerSerialRequired))
                {
                    throw new SignatureException(errors.InvalidSignature, Strings.SigningCertificateV2CertificateNotFound);
                }
            }

            if (signingCertificateAttribute != null)
            {
                var reader             = CreateDerSequenceReader(signingCertificateAttribute);
                var signingCertificate = SigningCertificate.Read(reader);

                if (signingCertificate.Certificates.Count == 0)
                {
                    throw new SignatureException(errors.InvalidSignature, Strings.SigningCertificateInvalid);
                }

                if (!IsMatch(signerInfo.Certificate, signingCertificate.Certificates[0]))
                {
                    throw new SignatureException(errors.InvalidSignature, Strings.SigningCertificateCertificateNotFound);
                }
            }

            var certificates = GetCertificateChain(signerInfo.Certificate, signedCms.Certificates, includeChain);

            if (certificates == null || certificates.Count == 0)
            {
                throw new SignatureException(errors.ChainBuildingFailed, Strings.CertificateChainBuildFailed);
            }

            return(certificates);
        }
        internal static bool IsTimestampValid(Timestamp timestamp, byte[] messageHash, bool failIfInvalid, List <SignatureLog> issues, SigningSpecifications spec)
        {
            var isValid = true;

            if (!timestamp.TstInfo.HasMessageHash(messageHash))
            {
                issues.Add(SignatureLog.Issue(failIfInvalid, NuGetLogCode.NU3019, Strings.TimestampIntegrityCheckFailed));
                isValid = false;
            }

            if (!spec.AllowedHashAlgorithmOids.Contains(timestamp.SignerInfo.DigestAlgorithm.Value))
            {
                issues.Add(SignatureLog.Issue(failIfInvalid, NuGetLogCode.NU3022, Strings.TimestampUnsupportedSignatureAlgorithm));
                isValid = false;
            }

            if (IsCertificateValidityPeriodInTheFuture(timestamp.SignerInfo.Certificate))
            {
                issues.Add(SignatureLog.Issue(failIfInvalid, NuGetLogCode.NU3025, Strings.TimestampNotYetValid));
                isValid = false;
            }

            return(isValid);
        }
Beispiel #27
0
        internal static SignatureVerificationStatusFlags ValidateTimestamp(Timestamp timestamp, Signature signature, bool treatIssuesAsErrors, List <SignatureLog> issues, SigningSpecifications spec)
        {
            if (timestamp == null)
            {
                throw new ArgumentNullException(nameof(timestamp));
            }
            if (signature == null)
            {
                throw new ArgumentNullException(nameof(signature));
            }
            if (issues == null)
            {
                throw new ArgumentNullException(nameof(issues));
            }

            // Default to specification v1
            spec = spec ?? SigningSpecifications.V1;

            var validationFlags = SignatureVerificationStatusFlags.NoErrors;
            var signerInfo      = timestamp.SignerInfo;

            if (timestamp.SignerInfo.Certificate != null)
            {
                try
                {
                    signerInfo.CheckSignature(verifySignatureOnly: true);
                }
                catch (Exception e)
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3021, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampSignatureValidationFailed, signature.FriendlyName)));
                    issues.Add(SignatureLog.DebugLog(e.ToString()));
                    validationFlags |= SignatureVerificationStatusFlags.SignatureCheckFailed;
                }

                if (!CertificateUtility.IsSignatureAlgorithmSupported(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3022, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampUnsupportedSignatureAlgorithm, signature.FriendlyName)));
                    validationFlags |= SignatureVerificationStatusFlags.SignatureAlgorithmUnsupported;
                }

                if (!CertificateUtility.IsCertificatePublicKeyValid(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3023, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampCertificateFailsPublicKeyLengthRequirement, signature.FriendlyName)));
                    validationFlags |= SignatureVerificationStatusFlags.CertificatePublicKeyInvalid;
                }

                if (!spec.AllowedHashAlgorithmOids.Contains(signerInfo.DigestAlgorithm.Value))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3024, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampUnsupportedSignatureAlgorithm, signature.FriendlyName)));
                    validationFlags |= SignatureVerificationStatusFlags.HashAlgorithmUnsupported;
                }

                try
                {
                    var hashAlgorithm  = CryptoHashUtility.OidToHashAlgorithmName(timestamp.TstInfo.HashAlgorithmId.Value);
                    var signatureValue = signature.GetSignatureValue();
                    var messageHash    = hashAlgorithm.ComputeHash(signatureValue);

                    if (!timestamp.TstInfo.HasMessageHash(messageHash))
                    {
                        issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3019, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampIntegrityCheckFailed, signature.FriendlyName)));
                        validationFlags |= SignatureVerificationStatusFlags.IntegrityCheckFailed;
                    }
                }
                catch
                {
                    // If the hash algorithm is not supported OidToHashAlgorithmName will throw
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3030, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampMessageImprintUnsupportedHashAlgorithm, signature.FriendlyName)));
                    validationFlags |= SignatureVerificationStatusFlags.MessageImprintUnsupportedAlgorithm;
                }

                if (CertificateUtility.IsCertificateValidityPeriodInTheFuture(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3025, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampNotYetValid, signature.FriendlyName)));
                    validationFlags |= SignatureVerificationStatusFlags.CertificateValidityInTheFuture;
                }

                if (!CertificateUtility.IsDateInsideValidityPeriod(signerInfo.Certificate, timestamp.GeneralizedTime))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3036, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampGeneralizedTimeInvalid, signature.FriendlyName)));
                    validationFlags |= SignatureVerificationStatusFlags.GeneralizedTimeOutsideValidity;
                }
            }
            else
            {
                issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3020, string.Format(CultureInfo.CurrentCulture, Strings.VerifyError_TimestampNoCertificate, signature.FriendlyName)));
                validationFlags |= SignatureVerificationStatusFlags.NoCertificate;
            }

            return(validationFlags);
        }
        internal static bool IsTimestampValid(Timestamp timestamp, Signature signature, bool treatIssuesAsErrors, List <SignatureLog> issues, SigningSpecifications spec)
        {
            if (timestamp == null)
            {
                throw new ArgumentNullException(nameof(timestamp));
            }
            if (signature == null)
            {
                throw new ArgumentNullException(nameof(signature));
            }
            if (issues == null)
            {
                throw new ArgumentNullException(nameof(issues));
            }

            // Default to specification v1
            spec = spec ?? SigningSpecifications.V1;

            var isValid    = true;
            var signerInfo = timestamp.SignerInfo;

            if (timestamp.SignerInfo.Certificate != null)
            {
                try
                {
                    signerInfo.CheckSignature(verifySignatureOnly: true);
                }
                catch (Exception e)
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3021, Strings.TimestampSignatureValidationFailed));
                    issues.Add(SignatureLog.DebugLog(e.ToString()));
                    isValid = false;
                }

                if (!CertificateUtility.IsSignatureAlgorithmSupported(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3022, Strings.TimestampUnsupportedSignatureAlgorithm));
                    isValid = false;
                }

                if (!CertificateUtility.IsCertificatePublicKeyValid(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3023, Strings.TimestampCertificateFailsPublicKeyLengthRequirement));
                    isValid = false;
                }

                if (!spec.AllowedHashAlgorithmOids.Contains(signerInfo.DigestAlgorithm.Value))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3024, Strings.TimestampUnsupportedSignatureAlgorithm));
                    isValid = false;
                }

                try
                {
                    var hashAlgorithm  = CryptoHashUtility.OidToHashAlgorithmName(timestamp.TstInfo.HashAlgorithmId.Value);
                    var signatureValue = signature.GetSignatureValue();
                    var messageHash    = hashAlgorithm.ComputeHash(signatureValue);

                    if (!timestamp.TstInfo.HasMessageHash(messageHash))
                    {
                        issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3019, Strings.TimestampIntegrityCheckFailed));
                        isValid = false;
                    }
                }
                catch
                {
                    // If the hash algorithm is not supported OidToHashAlgorithmName will throw
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3030, Strings.TimestampMessageImprintUnsupportedHashAlgorithm));
                    isValid = false;
                }

                if (CertificateUtility.IsCertificateValidityPeriodInTheFuture(signerInfo.Certificate))
                {
                    issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3025, Strings.TimestampNotYetValid));
                    isValid = false;
                }
            }
            else
            {
                issues.Add(SignatureLog.Issue(treatIssuesAsErrors, NuGetLogCode.NU3020, Strings.TimestampNoCertificate));
                isValid = false;
            }

            return(isValid);
        }