Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/Tasks/ManifestUtil/RSAPKCS1SHA384SignatureDescription.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;

#nullable disable

namespace System.Deployment.Internal.CodeSigning
{
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "RSAPKCS", Justification = "This casing is to match the existing RSAPKCS1SHA256SignatureDescription type")]
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SHA", Justification = "This casing is to match the use of SHA throughout the framework")]
public sealed class RSAPKCS1SHA384SignatureDescription : SignatureDescription
{
public RSAPKCS1SHA384SignatureDescription()
{
KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;
#if RUNTIME_TYPE_NETCORE
DigestAlgorithm = typeof(SHA384).FullName;
#else
DigestAlgorithm = typeof(SHA384Cng).FullName;
#endif
FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;
DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;
}

public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}

RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
deformatter.SetHashAlgorithm("SHA384");
return deformatter;
}

public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}

RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
formatter.SetHashAlgorithm("SHA384");
return formatter;
}
}
}
51 changes: 51 additions & 0 deletions src/Tasks/ManifestUtil/RSAPKCS1SHA512SignatureDescription.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics.CodeAnalysis;
using System.Security.Cryptography;

#nullable disable

namespace System.Deployment.Internal.CodeSigning
{
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "RSAPKCS", Justification = "This casing is to match the existing RSAPKCS1SHA1SignatureDescription type")]
[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "SHA", Justification = "This casing is to match the use of SHA throughout the framework")]
public sealed class RSAPKCS1SHA512SignatureDescription : SignatureDescription
{
public RSAPKCS1SHA512SignatureDescription()
{
KeyAlgorithm = typeof(RSACryptoServiceProvider).FullName;
#if RUNTIME_TYPE_NETCORE
DigestAlgorithm = typeof(SHA512).FullName;
#else
DigestAlgorithm = typeof(SHA512Cng).FullName;
#endif
FormatterAlgorithm = typeof(RSAPKCS1SignatureFormatter).FullName;
DeformatterAlgorithm = typeof(RSAPKCS1SignatureDeformatter).FullName;
}

public override AsymmetricSignatureDeformatter CreateDeformatter(AsymmetricAlgorithm key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}

RSAPKCS1SignatureDeformatter deformatter = new RSAPKCS1SignatureDeformatter(key);
deformatter.SetHashAlgorithm("SHA512");
return deformatter;
}

public override AsymmetricSignatureFormatter CreateFormatter(AsymmetricAlgorithm key)
{
if (key == null)
{
throw new ArgumentNullException(nameof(key));
}

RSAPKCS1SignatureFormatter formatter = new RSAPKCS1SignatureFormatter(key);
formatter.SetHashAlgorithm("SHA512");
return formatter;
}
}
}
52 changes: 29 additions & 23 deletions src/Tasks/ManifestUtil/SecurityUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -578,19 +578,19 @@ public static void SignFile(string certThumbprint,
throw new ArgumentException("TargetFrameworkVersion");
}

bool isTargetFrameworkSha256Supported = false;
bool isTargetFrameworkSha256OrHigherSupported = false;
if (String.IsNullOrEmpty(targetFrameworkIdentifier) ||
targetFrameworkIdentifier.Equals(Constants.DotNetFrameworkIdentifier, StringComparison.InvariantCultureIgnoreCase))
{
// SHA-256 digest can be parsed only with .NET 4.5 or higher.
isTargetFrameworkSha256Supported = targetVersion.CompareTo(s_dotNet45Version) >= 0;
isTargetFrameworkSha256OrHigherSupported = targetVersion.CompareTo(s_dotNet45Version) >= 0;
}
else if (targetFrameworkIdentifier.Equals(Constants.DotNetCoreAppIdentifier, StringComparison.InvariantCultureIgnoreCase))
{
// Use SHA-256 digest for .NET Core apps
isTargetFrameworkSha256Supported = true;
isTargetFrameworkSha256OrHigherSupported = true;
}
SignFileInternal(cert, timestampUrl, path, isTargetFrameworkSha256Supported, resources, disallowMansignTimestampFallback);
SignFileInternal(cert, timestampUrl, path, isTargetFrameworkSha256OrHigherSupported, resources, disallowMansignTimestampFallback);
}
else
{
Expand All @@ -614,7 +614,7 @@ public static void SignFile(string certPath, SecureString certPassword, Uri time
SignFile(cert, timestampUrl, path);
}

private static bool UseSha256Algorithm(X509Certificate2 cert)
private static bool UseSha256OrHigherAlgorithm(X509Certificate2 cert)
{
Oid oid = cert.SignatureAlgorithm;
// Issue 6732: Clickonce does not support sha384/sha512 file hash so we default to sha256
Expand All @@ -637,14 +637,14 @@ public static void SignFile(X509Certificate2 cert, Uri timestampUrl, string path
{
// setup resources
System.Resources.ResourceManager resources = new System.Resources.ResourceManager("Microsoft.Build.Tasks.Core.Strings.ManifestUtilities", typeof(SecurityUtilities).Module.Assembly);
SignFileInternal(cert, timestampUrl, path, targetFrameworkSupportsSha256: true, resources);
SignFileInternal(cert, timestampUrl, path, targetFrameworkSupportsSha256OrHigher: true, resources);
}

[SupportedOSPlatform("windows")]
private static void SignFileInternal(X509Certificate2 cert,
Uri timestampUrl,
string path,
bool targetFrameworkSupportsSha256,
bool targetFrameworkSupportsSha256OrHigher,
System.Resources.ResourceManager resources,
bool disallowMansignTimestampFallback = false)
{
Expand All @@ -663,13 +663,13 @@ private static void SignFileInternal(X509Certificate2 cert,
throw new FileNotFoundException(String.Format(CultureInfo.InvariantCulture, resources.GetString("SecurityUtil.SignTargetNotFound"), path), path);
}

bool useSha256 = UseSha256Algorithm(cert) && targetFrameworkSupportsSha256;
bool useSha256OrHigher = UseSha256OrHigherAlgorithm(cert) && targetFrameworkSupportsSha256OrHigher;

if (PathUtil.IsPEFile(path))
{
if (IsCertInStore(cert))
{
SignPEFile(cert, timestampUrl, path, resources, useSha256);
SignPEFile(cert, timestampUrl, path, resources, useSha256OrHigher);
}
else
{
Expand Down Expand Up @@ -702,17 +702,17 @@ private static void SignFileInternal(X509Certificate2 cert,
doc.Load(xr);
}

var manifest = new SignedCmiManifest2(doc, useSha256);
var manifest = new SignedCmiManifest2(doc, useSha256OrHigher);
CmiManifestSigner2 signer;
if (useSha256 && rsa is RSACryptoServiceProvider rsacsp)
if (useSha256OrHigher && rsa is RSACryptoServiceProvider rsacsp)
{
#pragma warning disable CA2000 // Dispose objects before losing scope because CmiManifestSigner2 will dispose the RSACryptoServiceProvider
signer = new CmiManifestSigner2(SignedCmiManifest2.GetFixedRSACryptoServiceProvider(rsacsp, useSha256), cert, useSha256);
signer = new CmiManifestSigner2(SignedCmiManifest2.GetFixedRSACryptoServiceProvider(rsacsp, useSha256OrHigher), cert, useSha256OrHigher);
#pragma warning restore CA2000 // Dispose objects before losing scope
}
else
{
signer = new CmiManifestSigner2(rsa, cert, useSha256);
signer = new CmiManifestSigner2(rsa, cert, useSha256OrHigher);
}

#if RUNTIME_TYPE_NETCORE
Expand Down Expand Up @@ -764,27 +764,27 @@ private static void SignFileInternal(X509Certificate2 cert,
}
}

private static void SignPEFile(X509Certificate2 cert, Uri timestampUrl, string path, System.Resources.ResourceManager resources, bool useSha256)
private static void SignPEFile(X509Certificate2 cert, Uri timestampUrl, string path, System.Resources.ResourceManager resources, bool useSha256OrHigher)
{
try
{
SignPEFileInternal(cert, timestampUrl, path, resources, useSha256, true);
SignPEFileInternal(cert, timestampUrl, path, resources, useSha256OrHigher, true);
}
catch (ApplicationException) when (timestampUrl != null)
{
// error, retry with signtool /t if timestamp url was given
SignPEFileInternal(cert, timestampUrl, path, resources, useSha256, false);
SignPEFileInternal(cert, timestampUrl, path, resources, useSha256OrHigher, false);
return;
}
}

private static void SignPEFileInternal(X509Certificate2 cert, Uri timestampUrl,
string path, System.Resources.ResourceManager resources,
bool useSha256, bool useRFC3161Timestamp)
bool useSha256OrHigher, bool useRFC3161Timestamp)
{
var startInfo = new ProcessStartInfo(
GetPathToTool(resources),
GetCommandLineParameters(cert.Thumbprint, timestampUrl, path, useSha256, useRFC3161Timestamp))
GetCommandLineParameters(cert, timestampUrl, path, useSha256OrHigher, useRFC3161Timestamp))
{
CreateNoWindow = true,
UseShellExecute = false,
Expand Down Expand Up @@ -825,17 +825,23 @@ private static void SignPEFileInternal(X509Certificate2 cert, Uri timestampUrl,
}
}

internal static string GetCommandLineParameters(string certThumbprint, Uri timestampUrl, string path,
bool useSha256, bool useRFC3161Timestamp)
internal static string GetCommandLineParameters(X509Certificate2 cert, Uri timestampUrl, string path,
bool useSha256OrHigher, bool useRFC3161Timestamp)
{
string hashAlgoName = ManifestSignatureMethods.GetHashAlgorithmName(cert);
if (string.IsNullOrEmpty(hashAlgoName))
{
throw new CryptographicException(System.Deployment.Internal.CodeSigning.Win32.CRYPT_E_UNKNOWN_ALGO);
}

var commandLine = new StringBuilder();
if (useSha256)
if (useSha256OrHigher)
{
commandLine.AppendFormat(CultureInfo.InvariantCulture, "sign /fd sha256 /sha1 {0} ", certThumbprint);
commandLine.AppendFormat(CultureInfo.InvariantCulture, "sign /fd {0} /sha1 {1} ", hashAlgoName, cert.Thumbprint);
}
else
{
commandLine.AppendFormat(CultureInfo.InvariantCulture, "sign /sha1 {0} ", certThumbprint);
commandLine.AppendFormat(CultureInfo.InvariantCulture, "sign /sha1 {0} ", cert.Thumbprint);
}

if (timestampUrl != null)
Expand Down
Loading