Example #1
0
        private static async Task <X509Certificate2> GetCertificateAsync(SignArgs signArgs)
        {
            var certFindOptions = new CertificateSourceOptions()
            {
                CertificatePath     = signArgs.CertificatePath,
                CertificatePassword = signArgs.CertificatePassword,
                Fingerprint         = signArgs.CertificateFingerprint,
                StoreLocation       = signArgs.CertificateStoreLocation,
                StoreName           = signArgs.CertificateStoreName,
                SubjectName         = signArgs.CertificateSubjectName,
                NonInteractive      = signArgs.NonInteractive,
                PasswordProvider    = signArgs.PasswordProvider,
                Token = signArgs.Token
            };

            // get matching certificates
            var matchingCertCollection = await CertificateProvider.GetCertificatesAsync(certFindOptions);

            if (matchingCertCollection.Count > 1)
            {
#if IS_DESKTOP
                if (signArgs.NonInteractive || !RuntimeEnvironmentHelper.IsWindows)
                {
                    // if on non-windows os or in non interactive mode - display the certs and error out
                    signArgs.Logger.LogInformation(CertificateUtility.X509Certificate2CollectionToString(matchingCertCollection, HashAlgorithmName.SHA256));
                    throw new SignCommandException(
                              LogMessage.CreateError(NuGetLogCode.NU3001,
                                                     string.Format(Strings.SignCommandMultipleCertException,
                                                                   nameof(SignArgs.CertificateFingerprint))));
                }
                else
                {
                    // Else launch UI to select
                    matchingCertCollection = X509Certificate2UI.SelectFromCollection(
                        FilterCodeSigningCertificates(matchingCertCollection),
                        Strings.SignCommandDialogTitle,
                        Strings.SignCommandDialogMessage,
                        X509SelectionFlag.SingleSelection);
                }
#else
                // if on non-windows os or in non interactive mode - display and error out
                signArgs.Logger.LogError(CertificateUtility.X509Certificate2CollectionToString(matchingCertCollection, HashAlgorithmName.SHA256));

                throw new SignCommandException(
                          LogMessage.CreateError(NuGetLogCode.NU3001,
                                                 string.Format(Strings.SignCommandMultipleCertException,
                                                               nameof(SignArgs.CertificateFingerprint))));
#endif
            }

            if (matchingCertCollection.Count == 0)
            {
                throw new SignCommandException(
                          LogMessage.CreateError(NuGetLogCode.NU3001,
                                                 Strings.SignCommandNoCertException));
            }

            return(matchingCertCollection[0]);
        }
        /// <summary>
        /// Looks for X509Certificates using the CertificateSourceOptions.
        /// Throws an InvalidOperationException if the option specifies a CertificateFilePath with invalid password.
        /// </summary>
        /// <param name="options">CertificateSourceOptions to be used while searching for the certificates.</param>
        /// <returns>An X509Certificate2Collection object containing matching certificates.
        /// If no matching certificates are found then it returns an empty collection.</returns>
        public static async Task <X509Certificate2Collection> GetCertificatesAsync(CertificateSourceOptions options)
        {
            // check certificate path
            var resultCollection = new X509Certificate2Collection();

            if (!string.IsNullOrEmpty(options.CertificatePath))
            {
                try
                {
                    var cert = await LoadCertificateFromFileAsync(options);

                    resultCollection = new X509Certificate2Collection(cert);
                }
                catch (CryptographicException ex)
                {
                    switch (ex.HResult)
                    {
                    case ERROR_INVALID_PASSWORD_HRESULT:
                    case OPENSSL_PKCS12_R_MAC_VERIFY_FAILURE:
                        throw new SignCommandException(
                                  LogMessage.CreateError(NuGetLogCode.NU3001,
                                                         string.Format(CultureInfo.CurrentCulture,
                                                                       Strings.SignCommandInvalidPasswordException,
                                                                       options.CertificatePath,
                                                                       nameof(options.CertificatePassword))));

                    case ERROR_FILE_NOT_FOUND_HRESULT:
                    case OPENSSL_BIO_R_NO_SUCH_FILE:
                        throw new SignCommandException(
                                  LogMessage.CreateError(NuGetLogCode.NU3001,
                                                         string.Format(CultureInfo.CurrentCulture,
                                                                       Strings.SignCommandCertificateFileNotFound,
                                                                       options.CertificatePath)));

                    case CRYPT_E_NO_MATCH_HRESULT:
                    case OPENSSL_ERR_R_NESTED_ASN1_ERROR:
                        throw new SignCommandException(
                                  LogMessage.CreateError(NuGetLogCode.NU3001,
                                                         string.Format(CultureInfo.CurrentCulture,
                                                                       Strings.SignCommandInvalidCertException,
                                                                       options.CertificatePath)));

                    default:
                        throw;
                    }
                }
            }
            else
            {
                resultCollection = LoadCertificateFromStore(options);
            }

            return(resultCollection);
        }
 private static void ValidateTimestampResponseNonce(
     byte[] nonce,
     Rfc3161TimestampToken timestampToken)
 {
     if (!nonce.SequenceEqual(timestampToken.TokenInfo.GetNonce()))
     {
         throw new TimestampException(LogMessage.CreateError(
                                          NuGetLogCode.NU3026,
                                          string.Format(CultureInfo.CurrentCulture,
                                                        Strings.TimestampResponseExceptionGeneral,
                                                        Strings.TimestampFailureNonceMismatch)));
     }
 }
        /// <summary>
        /// Logs an error if CLEAR is used with non-CLEAR entries.
        /// </summary>
        /// <returns>True if an invalid combination exists.</returns>
        public static bool LogErrorForClearIfInvalid(IEnumerable <string> values, string projectPath, ILogger logger)
        {
            if (HasInvalidClear(values))
            {
                var text    = string.Format(CultureInfo.CurrentCulture, Strings.CannotBeUsedWithOtherValues, Clear);
                var message = LogMessage.CreateError(NuGetLogCode.NU1002, text);
                message.ProjectPath = projectPath;
                logger.Log(message);

                return(true);
            }

            return(false);
        }
Example #5
0
 public ILogMessage ToLogMessage()
 {
     if (Level == LogLevel.Error)
     {
         return(LogMessage.CreateError(Code, Message));
     }
     else if (Level == LogLevel.Warning)
     {
         return(LogMessage.CreateWarning(Code, Message));
     }
     else
     {
         return(new LogMessage(Level, Message));
     }
 }
        /// <summary>
        /// Create a list of certificates in chain order with the leaf first and root last.
        /// </summary>
        /// <param name="certificate">The certificate for which a chain should be built.</param>
        /// <param name="extraStore">A certificate store containing additional certificates necessary
        /// for chain building.</param>
        /// <param name="logger">A logger.</param>
        /// <param name="certificateType">The certificate type.</param>
        /// <returns>A certificate chain.</returns>
        /// <remarks>This is intended to be used only during signing and timestamping operations,
        /// not verification.</remarks>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="certificate" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="extraStore" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="logger" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">Thrown if <paramref name="certificateType" /> is undefined.</exception>
        public static IX509CertificateChain GetCertificateChain(
            X509Certificate2 certificate,
            X509Certificate2Collection extraStore,
            ILogger logger,
            CertificateType certificateType)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

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

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

            if (!Enum.IsDefined(typeof(CertificateType), certificateType))
            {
                throw new ArgumentException(Strings.InvalidArgument, nameof(certificateType));
            }

            using (var chainHolder = new X509ChainHolder())
            {
                var chain = chainHolder.Chain;

                SetCertBuildChainPolicy(
                    chain.ChainPolicy,
                    extraStore,
                    DateTime.Now,
                    certificateType);

                chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;

                if (chain.Build(certificate))
                {
                    return(GetCertificateChain(chain));
                }

                X509ChainStatusFlags errorStatusFlags;
                X509ChainStatusFlags warningStatusFlags;

                GetChainStatusFlags(certificate, certificateType, out errorStatusFlags, out warningStatusFlags);

                var fatalStatuses = new List <X509ChainStatus>();
                var logCode       = certificateType == CertificateType.Timestamp ? NuGetLogCode.NU3028 : NuGetLogCode.NU3018;

                foreach (var chainStatus in chain.ChainStatus)
                {
                    if ((chainStatus.Status & errorStatusFlags) != 0)
                    {
                        fatalStatuses.Add(chainStatus);
                        logger.Log(LogMessage.CreateError(logCode, chainStatus.StatusInformation?.Trim()));
                    }
                    else if ((chainStatus.Status & warningStatusFlags) != 0)
                    {
                        logger.Log(LogMessage.CreateWarning(logCode, chainStatus.StatusInformation?.Trim()));
                    }
                }

                if (fatalStatuses.Any())
                {
                    if (certificateType == CertificateType.Timestamp)
                    {
                        throw new TimestampException(logCode, Strings.CertificateChainValidationFailed);
                    }

                    throw new SignatureException(logCode, Strings.CertificateChainValidationFailed);
                }

                return(GetCertificateChain(chain));
            }
        }
 public ILogMessage AsLogMessage()
 {
     return(LogMessage.CreateError(NuGetLogCode.NU1401, Message));
 }
        /// <summary>
        /// Create a list of certificates in chain order with the leaf first and root last.
        /// </summary>
        /// <remarks>This must not be used on timestamp certificates as this method does not enforce the requirement
        /// that timestamps be trusted.</remarks>
        /// <param name="certificate">The certificate for which a chain should be built.</param>
        /// <param name="extraStore">A certificate store containing additional certificates necessary
        /// for chain building.</param>
        /// <param name="logger">A logger.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="certificate" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="extraStore" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="logger" /> is <c>null</c>.</exception>
        public static IReadOnlyList <X509Certificate2> GetCertificateChainForSigning(
            X509Certificate2 certificate,
            X509Certificate2Collection extraStore,
            ILogger logger)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

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

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

            using (var chainHolder = new X509ChainHolder())
            {
                var chain = chainHolder.Chain;

                SetCertBuildChainPolicy(
                    chain.ChainPolicy,
                    extraStore,
                    DateTime.Now,
                    NuGetVerificationCertificateType.Signature);

                if (chain.Build(certificate))
                {
                    return(GetCertificateListFromChain(chain));
                }

                X509ChainStatusFlags errorStatusFlags;
                X509ChainStatusFlags warningStatusFlags;

                GetChainStatusFlagsForSigning(certificate, out errorStatusFlags, out warningStatusFlags);

                var fatalStatuses = new List <X509ChainStatus>();

                foreach (var chainStatus in chain.ChainStatus)
                {
                    if ((chainStatus.Status & errorStatusFlags) != 0)
                    {
                        fatalStatuses.Add(chainStatus);
                        logger.Log(LogMessage.CreateError(NuGetLogCode.NU3018, chainStatus.StatusInformation?.Trim()));
                    }
                    else if ((chainStatus.Status & warningStatusFlags) != 0)
                    {
                        logger.Log(LogMessage.CreateWarning(NuGetLogCode.NU3018, chainStatus.StatusInformation?.Trim()));
                    }
                }

                if (fatalStatuses.Any())
                {
                    throw new SignatureException(NuGetLogCode.NU3018, Strings.CertificateChainValidationFailed);
                }

                return(GetCertificateListFromChain(chain));
            }
        }
Example #9
0
 public override ILogMessage AsLogMessage()
 {
     return(LogMessage.CreateError(NuGetLogCode.NU1402, Message));
 }
        /// <summary>
        /// Timestamps data present in the TimestampRequest.
        /// </summary>
        public byte[] TimestampData(TimestampRequest request, ILogger logger, CancellationToken token)
        {
            token.ThrowIfCancellationRequested();

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

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

            // Get the signatureValue from the signerInfo object
            using (var signatureNativeCms = NativeCms.Decode(request.SignatureValue, detached: false))
            {
                var signatureValueHashByteArray = NativeCms.GetSignatureValueHash(
                    request.TimestampHashAlgorithm,
                    signatureNativeCms);

                // Allows us to track the request.
                var nonce = GenerateNonce();
                var rfc3161TimestampRequest = new Rfc3161TimestampRequest(
                    signatureValueHashByteArray,
                    request.TimestampHashAlgorithm.ConvertToSystemSecurityHashAlgorithmName(),
                    nonce: nonce,
                    requestSignerCertificates: true);

                // Request a timestamp
                // The response status need not be checked here as lower level api will throw if the response is invalid
                var timestampToken = rfc3161TimestampRequest.SubmitRequest(
                    _timestamperUrl,
                    TimeSpan.FromSeconds(_rfc3161RequestTimeoutSeconds));

                // ensure response is for this request
                ValidateTimestampResponseNonce(nonce, timestampToken);

                var timestampCms = timestampToken.AsSignedCms();

                byte[] timestampByteArray;

                using (var timestampNativeCms = NativeCms.Decode(timestampCms.Encode(), detached: false))
                    using (var timestampCertChain = new X509Chain())
                    {
                        var policy = timestampCertChain.ChainPolicy;

                        policy.ApplicationPolicy.Add(new Oid(Oids.TimeStampingEkuOid));
                        policy.VerificationFlags = X509VerificationFlags.IgnoreNotTimeValid;

                        policy.ExtraStore.AddRange(timestampCms.Certificates);

                        policy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
                        policy.RevocationMode = X509RevocationMode.Online;

                        var timestampSignerCertificate = GetTimestampSignerCertificate(timestampCms);
                        if (DateTime.Now < timestampSignerCertificate.NotBefore)
                        {
                            throw new TimestampException(LogMessage.CreateError(
                                                             NuGetLogCode.NU3025,
                                                             string.Format(CultureInfo.CurrentCulture,
                                                                           Strings.TimestampCertificateInvalid,
                                                                           $"{Environment.NewLine}{CertificateUtility.X509Certificate2ToString(timestampSignerCertificate)}")));
                        }

                        if (!timestampCertChain.Build(timestampSignerCertificate))
                        {
                            throw new TimestampException(LogMessage.CreateError(
                                                             NuGetLogCode.NU3028,
                                                             string.Format(CultureInfo.CurrentCulture,
                                                                           Strings.TimestampCertificateChainBuildFailure,
                                                                           $"{Environment.NewLine}{CertificateUtility.X509Certificate2ToString(timestampSignerCertificate)}")));
                        }

                        // Insert all the certificates into timestampCms
                        InsertTimestampCertChainIntoTimestampCms(timestampCms, timestampCertChain, timestampNativeCms);
                        timestampByteArray = timestampCms.Encode();
                    }

                signatureNativeCms.AddTimestamp(timestampByteArray);

                return(signatureNativeCms.Encode());
            }
        }