Skip to content
Merged
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog for OpenAuthenticode

## v0.6.1 - 2025-02-12

* Fix up certificate selection logic for `Get-OpenAuthenticodeAzTrustedSigner` to retrieve the correct leaf certificate on Windows.

## v0.6.0 - 2025-02-12

* Added the `-TokenSource` parameter for `Get-OpenAuthenticodeAzKey` to specify the authentication method used.
Expand Down
2 changes: 1 addition & 1 deletion module/OpenAuthenticode.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
RootModule = 'OpenAuthenticode.psm1'

# Version number of this module.
ModuleVersion = '0.6.0'
ModuleVersion = '0.6.1'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
WriteVerbose("Importing certificate chain");
X509Certificate2Collection chain = [];
chain.Import(rawChain);
X509Certificate2 cert = chain[0];

X509Certificate2 cert = CertificateHelper.GetAzureTrustedSigningCertificate(chain, cmdlet: this);

Check warning on line 83 in src/OpenAuthenticode.Module/OpenAuthenticodeAzTrustedSigner.cs

View check run for this annotation

Codecov / codecov/patch

src/OpenAuthenticode.Module/OpenAuthenticodeAzTrustedSigner.cs#L83

Added line #L83 was not covered by tests
WriteVerbose($"Creating AzureTrustedSigner object with cert '{cert.SubjectName.Name}' - {cert.Thumbprint}");

try
Expand Down
48 changes: 48 additions & 0 deletions src/OpenAuthenticode/CertificateHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.Management.Automation;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;

namespace OpenAuthenticode;

internal static class CertificateHelper
{

/// <summary>
/// The order of cert in the collection is platform specific. We manually
/// find the Azure Trusted Signing cert by the one with an EKU that is the
/// Azure Trusted Signing OID prefix '1.3.6.1.4.1.311.97.'.
/// </summary>
/// <param name="collection">The collection to search.</param>
/// <param name="cmdlet">The cmdlet to write verbose messages to.</param>
/// <returns>The leaf certificate to use for signing.</returns>
/// <exception cref="ItemNotFoundException">Leaf certificate was not found.</exception>
public static X509Certificate2 GetAzureTrustedSigningCertificate(
X509Certificate2Collection collection,
AsyncPSCmdlet? cmdlet = null)
{
foreach (X509Certificate2 cert in collection)
{
cmdlet?.WriteVerbose(
$"Processing Azure Trusted Signing certificate: Subject '{cert.Subject}' - Issuer '{cert.Issuer}'");

foreach (X509Extension ext in cert.Extensions)
{
if (ext is not X509EnhancedKeyUsageExtension eku)
{
continue;
}

foreach (Oid oid in eku.EnhancedKeyUsages)
{
if (oid?.Value?.StartsWith("1.3.6.1.4.1.311.97.") == true)
{
return cert;
}
}
}

Check warning on line 42 in src/OpenAuthenticode/CertificateHelper.cs

View check run for this annotation

Codecov / codecov/patch

src/OpenAuthenticode/CertificateHelper.cs#L42

Added line #L42 was not covered by tests
}

// This should not happen but just in case.
throw new ItemNotFoundException("Failed to find leaf certificate in Azure Trusted Signing collection.");
}
}
5 changes: 5 additions & 0 deletions src/OpenAuthenticode/ECDsaPrivateKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace OpenAuthenticode;

internal abstract class ECDsaPrivateKey : ECDsa
{
public ECDsaPrivateKey(int keySize)
{
KeySizeValue = keySize;
}

public abstract byte[] SignHashCore(byte[] hash);

public override byte[] SignHash(byte[] hash) => SignHashCore(hash);
Expand Down
8 changes: 4 additions & 4 deletions src/OpenAuthenticode/KeyProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ internal KeyProvider(
DefaultHashAlgorithm = defaultHashAlgorithm;
Key = keyType switch
{
KeyType.RSA => new CachedRSAPrivateKey(this),
KeyType.ECDsa => new CachedECDsaPrivateKey(this),
KeyType.RSA => new CachedRSAPrivateKey(this, certificate.GetRSAPublicKey()!.KeySize),
KeyType.ECDsa => new CachedECDsaPrivateKey(this, certificate.GetECDsaPublicKey()!.KeySize),
_ => throw new NotImplementedException(),
};
}
Expand Down Expand Up @@ -265,7 +265,7 @@ private sealed class CachedRSAPrivateKey : RSAPrivateKey
{
private readonly KeyProvider _provider;

public CachedRSAPrivateKey(KeyProvider provider)
public CachedRSAPrivateKey(KeyProvider provider, int keySize) : base(keySize)
{
_provider = provider;
}
Expand All @@ -278,7 +278,7 @@ private sealed class CachedECDsaPrivateKey : ECDsaPrivateKey
{
private readonly KeyProvider _provider;

public CachedECDsaPrivateKey(KeyProvider provider)
public CachedECDsaPrivateKey(KeyProvider provider, int keySize) : base(keySize)
{
_provider = provider;
}
Expand Down
3 changes: 0 additions & 3 deletions src/OpenAuthenticode/LoadContext.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;

[assembly: InternalsVisibleTo("OpenAuthenticode.Module")]

namespace OpenAuthenticode;

public class LoadContext : AssemblyLoadContext
Expand Down
5 changes: 5 additions & 0 deletions src/OpenAuthenticode/OpenAuthenticode.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="all"/>
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="OpenAuthenticode.Module" />
<InternalsVisibleTo Include="OpenAuthenticodeTests" />
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions src/OpenAuthenticode/RSAPrivateKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ namespace OpenAuthenticode;

internal abstract class RSAPrivateKey : RSA
{
public RSAPrivateKey(int keySize)
{
KeySizeValue = keySize;
}

public abstract byte[] SignHashCore(byte[] hash, HashAlgorithmName hashAlgorithm);

public override byte[] SignHash(
Expand Down
37 changes: 37 additions & 0 deletions tests/units/OpenAuthenticodeTests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Xunit.SkippableFact" Version="1.5.23" />
</ItemGroup>

<ItemGroup>
<!--
S.M.A brings in these deps but we don't rely on it directly. It's up to
the user to run with a newer PowerShell version that isn't affected.
-->
<NuGetAuditSuppress Include="https://github.com/advisories/GHSA-447r-wph3-92pm" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../../src/OpenAuthenticode/OpenAuthenticode.csproj" />
<PackageReference Include="System.Management.Automation" Version="7.4.0" />
</ItemGroup>

</Project>
27 changes: 27 additions & 0 deletions tests/units/SignatureHelperTests.cs

Large diffs are not rendered by default.