Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenSslCryptographicException: error:03000098:digital envelope routines::invalid digest on CentOS Stream 9 #65874

Closed
omajid opened this issue Feb 25, 2022 · 52 comments · Fixed by #69668

Comments

@omajid
Copy link
Member

omajid commented Feb 25, 2022

Description

While building .NET 6 using .NET 6 in in CentOS Stream 9 (aka RHEL 9 in-development), I am running into error : Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:03000098:digital envelope routines::invalid digest

error : Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:03000098:digital envelope routines::invalid digest 
error :    at Interop.Crypto.RsaSignHash(SafeEvpPKeyHandle pkey, RSASignaturePaddingMode paddingMode, IntPtr digestAlgorithm, ReadOnlySpan`1 hash, Span`1 destination) 
error :    at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.TrySignHash(ReadOnlySpan`1 hash, Span`1 destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, Boolean allocateSignature, Int32& bytesWritten, Byte[]& signature) 
error :    at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) 
error :    at Microsoft.CodeAnalysis.SigningUtilities.CalculateRsaSignature(IEnumerable`1 content, RSAParameters privateKey) 
error :    at Microsoft.CodeAnalysis.DesktopStrongNameProvider.<>c__DisplayClass12_0.<SignBuilder>b__0(IEnumerable`1 content) 
error :    at System.Reflection.PortableExecutable.PEBuilder.Sign(BlobBuilder peImage, Blob strongNameSignatureFixup, Func`2 signatureProvider) 
error :    at System.Reflection.PortableExecutable.ManagedPEBuilder.Sign(BlobBuilder peImage, Func`2 signatureProvider) 
error :    at Microsoft.CodeAnalysis.DesktopStrongNameProvider.SignBuilder(ExtendedPEBuilder peBuilder, BlobBuilder peBlob, RSAParameters privateKey) 
error :    at Microsoft.Cci.PeWriter.WritePeToStream(EmitContext context, CommonMessageProvider messageProvider, Func`1 getPeStream, Func`1 getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, String pdbPathOpt, Boolean metadataOnly, Boolean isDeterministic, Boolean emitTestCoverageData, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.Compilation.SerializePeToStream(CommonPEModuleBuilder moduleBeingBuilt, DiagnosticBag metadataDiagnostics, CommonMessageProvider messageProvider, Func`1 getPeStream, Func`1 getMetadataPeStreamOpt, Func`1 getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, String pdbPathOpt, RebuildData rebuildData, Boolean metadataOnly, Boolean includePrivateMembers, Boolean isDeterministic, Boolean emitTestCoverageData, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.Compilation.SerializeToPeStream(CommonPEModuleBuilder moduleBeingBuilt, EmitStreamProvider peStreamProvider, EmitStreamProvider metadataPEStreamProvider, EmitStreamProvider pdbStreamProvider, RebuildData rebuildData, Func`2 testSymWriterFactory, DiagnosticBag diagnostics, EmitOptions emitOptions, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.CommonCompiler.CompileAndEmit(TouchedFileLogger touchedFilesLogger, Compilation& compilation, ImmutableArray`1 analyzers, ImmutableArray`1 generators, ImmutableArray`1 additionalTextFiles, AnalyzerConfigSet analyzerConfigSet, ImmutableArray`1 sourceFileAnalyzerConfigOptions, ImmutableArray`1 embeddedTexts, DiagnosticBag diagnostics, CancellationToken cancellationToken, CancellationTokenSource& analyzerCts, Boolean& reportAnalyzer, AnalyzerDriver& analyzerDriver) 
error :    at Microsoft.CodeAnalysis.CommonCompiler.RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.CommonCompiler.Run(TextWriter consoleOutput, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.<>c__DisplayClass1_0.<Run>b__0(TextWriter tw) 
error :    at Microsoft.CodeAnalysis.CommandLine.ConsoleUtil.RunWithUtf8Output[T](Boolean utf8Output, TextWriter textWriter, Func`2 func) 
error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.Run(String[] args, BuildPaths buildPaths, TextWriter textWriter, IAnalyzerAssemblyLoader analyzerLoader) 
error :    at Microsoft.CodeAnalysis.CommandLine.BuildClient.RunCompilation(IEnumerable`1 originalArguments, BuildPaths buildPaths, TextWriter textWriter, String pipeName) 
error :    at Microsoft.CodeAnalysis.CommandLine.BuildClient.Run(IEnumerable`1 arguments, RequestLanguage language, CompileFunc compileFunc, CompileOnServerFunc compileOnServerFunc) 
error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Program.MainCore(String[] args) 

Full log is here: https://centos.softwarefactory-project.io/zuul/t/centos/build/b00c0fe1895c4e1487350108a41214da

Could this be caused by Disable SHA1 signature creation and verification by default?

Reproduction Steps

It seems like building runtime in a CentOS Stream 9 container should be enough to trigger the bug. Will test and update this step later.

Expected behavior

I can build .NET itself.

Actual behavior

I can't build .NET, because the compiler needs signing (via OpenSSL) to work.

Regression?

It's a regression somewhere. Most likely it's not .NET itself that's to blame, because this same source code (no changes) built a few days ago.

Known Workarounds

I am testing if an export OPENSSL_ENABLE_SHA1_SIGNATURES=1 will work around the issue.

Edit: Confirmed. It does make the build move past this particular error.

Configuration

  • .NET 6 source-build using the 6.0.102 tag of dotnet/installer
  • CentOS Stream 9 on x86_64

Other information

No response

@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Security untriaged New issue has not been triaged by the area owner labels Feb 25, 2022
@ghost
Copy link

ghost commented Feb 25, 2022

Tagging subscribers to this area: @dotnet/area-system-security, @vcsjones
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

While building .NET 6 using .NET 6 in in CentOS Stream 9 (aka RHEL 9 in-development), I am running into error : Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:03000098:digital envelope routines::invalid digest

error : Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:03000098:digital envelope routines::invalid digest 
error :    at Interop.Crypto.RsaSignHash(SafeEvpPKeyHandle pkey, RSASignaturePaddingMode paddingMode, IntPtr digestAlgorithm, ReadOnlySpan`1 hash, Span`1 destination) 
error :    at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.TrySignHash(ReadOnlySpan`1 hash, Span`1 destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, Boolean allocateSignature, Int32& bytesWritten, Byte[]& signature) 
error :    at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) 
error :    at Microsoft.CodeAnalysis.SigningUtilities.CalculateRsaSignature(IEnumerable`1 content, RSAParameters privateKey) 
error :    at Microsoft.CodeAnalysis.DesktopStrongNameProvider.<>c__DisplayClass12_0.<SignBuilder>b__0(IEnumerable`1 content) 
error :    at System.Reflection.PortableExecutable.PEBuilder.Sign(BlobBuilder peImage, Blob strongNameSignatureFixup, Func`2 signatureProvider) 
error :    at System.Reflection.PortableExecutable.ManagedPEBuilder.Sign(BlobBuilder peImage, Func`2 signatureProvider) 
error :    at Microsoft.CodeAnalysis.DesktopStrongNameProvider.SignBuilder(ExtendedPEBuilder peBuilder, BlobBuilder peBlob, RSAParameters privateKey) 
error :    at Microsoft.Cci.PeWriter.WritePeToStream(EmitContext context, CommonMessageProvider messageProvider, Func`1 getPeStream, Func`1 getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, String pdbPathOpt, Boolean metadataOnly, Boolean isDeterministic, Boolean emitTestCoverageData, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.Compilation.SerializePeToStream(CommonPEModuleBuilder moduleBeingBuilt, DiagnosticBag metadataDiagnostics, CommonMessageProvider messageProvider, Func`1 getPeStream, Func`1 getMetadataPeStreamOpt, Func`1 getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, String pdbPathOpt, RebuildData rebuildData, Boolean metadataOnly, Boolean includePrivateMembers, Boolean isDeterministic, Boolean emitTestCoverageData, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.Compilation.SerializeToPeStream(CommonPEModuleBuilder moduleBeingBuilt, EmitStreamProvider peStreamProvider, EmitStreamProvider metadataPEStreamProvider, EmitStreamProvider pdbStreamProvider, RebuildData rebuildData, Func`2 testSymWriterFactory, DiagnosticBag diagnostics, EmitOptions emitOptions, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.CommonCompiler.CompileAndEmit(TouchedFileLogger touchedFilesLogger, Compilation& compilation, ImmutableArray`1 analyzers, ImmutableArray`1 generators, ImmutableArray`1 additionalTextFiles, AnalyzerConfigSet analyzerConfigSet, ImmutableArray`1 sourceFileAnalyzerConfigOptions, ImmutableArray`1 embeddedTexts, DiagnosticBag diagnostics, CancellationToken cancellationToken, CancellationTokenSource& analyzerCts, Boolean& reportAnalyzer, AnalyzerDriver& analyzerDriver) 
error :    at Microsoft.CodeAnalysis.CommonCompiler.RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.CommonCompiler.Run(TextWriter consoleOutput, CancellationToken cancellationToken) 
error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.<>c__DisplayClass1_0.<Run>b__0(TextWriter tw) 
error :    at Microsoft.CodeAnalysis.CommandLine.ConsoleUtil.RunWithUtf8Output[T](Boolean utf8Output, TextWriter textWriter, Func`2 func) 
error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.Run(String[] args, BuildPaths buildPaths, TextWriter textWriter, IAnalyzerAssemblyLoader analyzerLoader) 
error :    at Microsoft.CodeAnalysis.CommandLine.BuildClient.RunCompilation(IEnumerable`1 originalArguments, BuildPaths buildPaths, TextWriter textWriter, String pipeName) 
error :    at Microsoft.CodeAnalysis.CommandLine.BuildClient.Run(IEnumerable`1 arguments, RequestLanguage language, CompileFunc compileFunc, CompileOnServerFunc compileOnServerFunc) 
error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Program.MainCore(String[] args) 

Full log is here: https://centos.softwarefactory-project.io/zuul/t/centos/build/b00c0fe1895c4e1487350108a41214da

Could this be caused by Disable SHA1 signature creation and verification by default?

Reproduction Steps

It seems like building runtime in a CentOS Stream 9 container should be enough to trigger the bug. Will test and update this step later.

Expected behavior

I can build .NET itself.

Actual behavior

I can't build .NET, because the compiler needs signing (via OpenSSL) to work.

Regression?

It's a regression somewhere. Most likely it's not .NET itself that's to blame, because this same source code (no changes) built a few days ago.

Known Workarounds

I am testing if an export OPENSSL_ENABLE_SHA1_SIGNATURES=1 will work around the issue.

Configuration

  • .NET 6 source-build using the 6.0.102 tag of dotnet/installer
  • CentOS Stream 9 on x86_64

Other information

No response

Author: omajid
Assignees: -
Labels:

area-System.Security, untriaged

Milestone: -

@vcsjones
Copy link
Member

Could this be caused by Disable SHA1 signature creation and verification by default?

Seems likely. It's trying to produce a strong name signature and that uses RSA-SHA1:

https://github.com/dotnet/roslyn/blob/315c2e149ba7889b0937d872274c33fcbfe9af5f/src/Compilers/Core/Portable/PEWriter/SigningUtilities.cs#L22

@omajid
Copy link
Member Author

omajid commented Feb 25, 2022

Thanks for the pointer.

I tried a build with a workaround to enable SHA1 and it seems to be working. It does seem to be down to SHA1 signature creation being disabled.

How difficult would be be to switch to something slightly better for a future release of .NET? I have no knowledge of Windows, but I found a blog post that suggests SHA256 and SHA512 are also supported for signing?

@vcsjones
Copy link
Member

How difficult would be be to switch to something slightly better for a future release of .NET? I have no knowledge of Windows,

My understanding is that this RSA-SHA1 is being used for .NET's strong naming functionality, not Windows Authenticode. The Authenticode signatures are likely already SHA256.

I don't know what it would take to move the ecosystem past RSA-SHA1 for the purpose that it is being used. Perhaps @bartonjs or @GrabYourPitchforks know, directly or indirectly.

@vcsjones
Copy link
Member

vcsjones commented Feb 25, 2022

For what it's worth, this breaks any .NET project that uses strong name signing, not just building .NET itself.

To reproduce, create a new C# project. Add this somewhere:

[assembly:System.Reflection.AssemblyKeyFile("testkey.snk")]

Grab a strong name key. You can use testkey.snk in this repository. Put it next to the csproj.

It will fail to build with the same error.

@jaredpar
Copy link
Member

My understanding is that this RSA-SHA1 is being used for .NET's strong naming functionality, not Windows Authenticode

That is correct for this scenario / stack trace

@bartonjs
Copy link
Member

ECMA-335 only describes RSA(SSA)-SHA1(-PKCS1v1_5):

The Strong Name (SN) signing process uses standard hash and cipher algorithms for Strong name
signing. An SHA-1 hash over most of the PE file is generated. That hash value is RSA-signed with the
SN private key. For verification purposes the public key is stored into the PE file as well as the signed
hash value.

There's a concept of "extended strong name", which is a SHA256 countersignature on the SHA-1 signature (similar to how Authenticode bootstrapped SHA256); but I don't think that there's a Strong Name scenario that avoids SHA-1.

While Strong Name isn't important for .NET Core / .NET 5+, I can imagine RHEL users building components (such as the Roslyn C# compiler) that need to support Strong Name for .NET Framework-based customers (either a .NET Standard library or even building directly for a .NET Framework TFM).

I don't know how dotnet build works (e.g. does it launch a second process?), but perhaps there's a way for the RHEL build of the SDK to always assert OPENSSL_ENABLE_SHA1_SIGNATURES=1 in the environment when using dotnet build?

@vcsjones
Copy link
Member

Additionally, I did a quick search to see if there are other things in the dotnet org that use RSA+SHA1 and strong name signing is the only meaningful result.

https://cs.github.com/?scopeName=All+repos&scope=&q=org%3Adotnet+%2F%28Sign%7CVerify%29%28Hash%7CData%29%5C%28.*HashAlgorithmName.SHA1%2F+NOT+path%3A%2Ftests%3F%2F

@omajid
Copy link
Member Author

omajid commented Mar 2, 2022

I reported this to the roslyn folks directly as well, at dotnet/roslyn#59880, particularly because I am not sure if roslyn's usage of SHA1 qualifies as "security" or not.

@jaredpar
Copy link
Member

jaredpar commented Mar 3, 2022

@omajid I responded to the issue in dotnet/roslyn. In summary though this isn't a decision the roslyn compiler is making. The .NET platform requires SHA-1 be used for strong naming. The roslyn compiler, and every other .NET compiler that supports strong naming, is simply implementing the specification here. There are no other options besides SHA-1 unless the underlying format is changed.

@omajid
Copy link
Member Author

omajid commented Mar 3, 2022

Thanks, @jaredpar

The .NET platform requires SHA-1 be used for strong naming

What should the platform do when (RSA+)SHA1 is not available on the OS (because of policies like FIPS, or general system hardening)? Should it hard-fail like it does now? Should it have a separate this-is-not-security implementation of RSA+SHA1?

Is there a way to tell OpenSSL "we want to use RSA+SHA1, but not for security, we promise"?

There are no other options besides SHA-1 unless the underlying format is changed.

Given how SHA1 is being phased out everywhere, what would it take to update the underlying format?

@omajid
Copy link
Member Author

omajid commented Mar 3, 2022

Perhaps there's a way for the RHEL build of the SDK to always assert OPENSSL_ENABLE_SHA1_SIGNATURES=1 in the environment when using dotnet build?

I slept over this one, and I wonder if this will allow using RSA+SHA1 even in contexts where the OS really doesn't want it to be used, eg for TLS when downloading nuget packages (that happens as part of dotnet build, right?).

And it wont help when FIPS enablement permanently disables RSA+SHA1.

@vcsjones
Copy link
Member

vcsjones commented Mar 3, 2022

Is there a way to tell OpenSSL "we want to use RSA+SHA1, but not for security, we promise"?

Correct me if I am wrong, but this is a patch on top of OpenSSL developed by RedHat, not something that is in OpenSSL upstream, correct? It would then be up to RedHat to implement a work around, if one needs to be provided.

Based on the changeset, it looks like developers can:

  1. Set rh-allow-sha1-signatures in openssl.cnf to permanently re-allow SHA1 signatures.
  2. Use the environment variable, as you have already described.

Even if RedHat provided an option for "pinky swear it's not for security", it would require the runtime detect this custom API from RedHat, and somehow expose this option to roslyn and fsharp compilers.

Alternatively, the roslyn and fsharp compilers could consider using a private implementation, say one written in managed code, of RSA and not use OpenSSL at all. I don't know if that is at all feasible or not.

@jaredpar
Copy link
Member

jaredpar commented Mar 3, 2022

Alternatively, the roslyn and fsharp compilers could consider using a private implementation, say one written in managed code, of RSA and not use OpenSSL at all. I don't know if that is at all feasible or not.

I don't think having a private implementation in Roslyn / F# is the right answer. That means every compiler team has to own their own copy of SHA-1, we all have to individually justify it to the security bugs that will come every 6 months (even justifying the enum value of SHA1 is painful). It also means 3rd party .NET compilers have to do the same.

If we go the private implementation route I think the best approach is put into the PEBuilder type directly, make it private and have a Sign overload that uses this implementation. That makes it clear it is only used for ECMA-335 compliance for which there is a known SHA-1 exception.

Given how SHA1 is being phased out everywhere, what would it take to update the underlying format?

@jkotas and @davidwrighton are the best to answer that question authoritatively. But my understanding is that the answer is a lot. Consider that it's not just updating for .NET Core. In order for the update to solve this problem we also need to update it for .NET Framework. Further it probably needs to be updated for all versions of .NET Framework that netstandard2.0 maps to. That is a huge cost.

@bartonjs
Copy link
Member

bartonjs commented Mar 3, 2022

Given how SHA1 is being phased out everywhere, what would it take to update the underlying format?

Personally, I think it's one of those "there's not enough money on the planet" problems. My understanding is that the main reason that Roslyn still has Strong Name support is for .NET Framework compatibility. .NET Framework can't support anything other than RSASSA-SHA1-PKCS1-v1_5 without first making the change (which seems obvious... but seems against our current level of support for it) and then waiting for it to be deployed pretty much everywhere in the world (beautiful in-place upgrade SxS protocol delays)... and then could finally start using it. Oh, and it may or may not require first adding a revision to ECMA-335 (not sure if that spec lags or precedes implementation).

Should it have a separate this-is-not-security implementation of RSA+SHA1?

It's certainly... possible. But, personally, I think that the answer is "operating environments that do not allow RSA+SHA1 can not be used with scenarios that need to produce assemblies with strong names". Further information over time could, of course, change our position here.

And it wont help when FIPS enablement permanently disables RSA+SHA1.

In Windows, at least, FIPSyness has never blocked algorithms. The OS team's view is that the application can make the decision as to whether their attempt to use a non-FIPS-approved algorithm is valid. As far as I understand things, FIPS only applies when cryptography is used for a security decision... e.g. MD5 is not FIPS-Approved, but you don't lose government contracts for using the Content-MD5 HTTP header, since it's not security. .NET's position is that strong name is not a security feature... ergo, no FIPS implication.

I'm personally not sure what OpenSSL 3's FIPS module is going to do here (fall back to default/legacy if you ask for non-FIPS modes of operation, or fail).

That means every compiler team has to own their own copy of SHA-1

Actually, it'd be their own copy of RSA (specifically, RSASSA-PKCS1-v1_5 signing)... the SHA-1 by itself works fine.

@jaredpar
Copy link
Member

jaredpar commented Mar 3, 2022

My understanding is that the main reason that Roslyn still has Strong Name support is for .NET Framework compatibility

Prefer we stop referring to this as a Roslyn problem because it keeps leading to Roslyn based solutions, Roslyn issues, etc ... This is a .NET Compiler problem. It impacts F# just as much as Roslyn.

That means every compiler team has to own their own copy of SHA-1

Actually, it'd be their own copy of RSA (specifically, RSASSA-PKCS1-v1_5 signing)... the SHA-1 by itself works fine.

Gotcha

@jkotas
Copy link
Member

jkotas commented Mar 3, 2022

operating environments that do not allow RSA+SHA1 can not be used with scenarios that need to produce assemblies with strong names

I agree. If you need to produce assembly that is fully compatible with .NET Framework, you need to have RSA1+SHA1. If you do not need it to be fully compatible with .NET Framework, use public signing. Note that the public signed binaries still work on .NET Framework in most scenarios.

Maybe the resolution for this is to change the defaults somewhere? Public sign by default, require opt-in into full signing?

@jaredpar
Copy link
Member

jaredpar commented Mar 3, 2022

Maybe the resolution for this is to change the defaults somewhere? Public sign by default, require opt-in into full signing?

I think changing the default for .NET Core target frameworks is reasonable. It should not have any impact.

For netstandard2.0 and .NET Framework target frameworks though it seems a lot dicier. To address this problem we'd need to flip the defaults for these target frameworks to. That is necessary at a fundamental level because even our own source build, which must work on RedHat, uses these target frameworks. It's also reasonable for customers to build these target frameworks on RedHat. So seems like we have to include them in the change.

So say for example in .NET 7 we made the call to do public sign by default and force people who want real sign to opt into it. That seems like a reasonable stance to take. Problem is how do we communicate this to customers? Worry we could quickly end up in a place where people upgrade to .NET 7, everything passes tests but fails in deployment because that is the place which was most likely to rely on strong named binaries.

@jkotas
Copy link
Member

jkotas commented Mar 3, 2022

For netstandard2.0 and .NET Framework target frameworks though it seems a lot dicier.

Agree. I do not think it is worth the pain to be changing default for these. If you need to target legacy systems, you need to have legacy build machine configuration.

@omajid
Copy link
Member Author

omajid commented Mar 21, 2022

Thanks, everyone for the discussion.

For now, I see two paths forward for users, and no action needed on the .NET side:

  • Users should use PublicSigning, through something like this in their project file

    <PropertyGroup>
      <SignAssembly>True</SignAssembly>
      <PublicSign>True</PublicSign> 
      <AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
    </PropertyGroup>
  • Users should re-enable SHA1+RSA, through some OpenSSL configuration. This wont work in FIPS mode.

    This might be through something like this shell command:

    # update-crypto-policies --set LEGACY

    Or it might be through a special environment variable and/or configuration option (which are less well supported/stable than this LEGACY switch).

Is there anything else that needs to be done? Shall I close this issue? Is this worth documenting somewhere?

@bartonjs
Copy link
Member

Is this worth documenting somewhere?

I'm not sure where/what we'd document.

From the RSA perspective, it only applies when on Fedora/CentOS/RHEL when using RSAOpenSsl or RSA.Create() (a custom RSA implementation, such as RSAKeyVault, wouldn't necessarily have the problem), and at best we'd just link to the RedHat crypto docs for it. (From an API perspective, it's covered under the blanket docs of "if something goes wrong: CryptographicException"... and this is just "the underlying provider doesn't support the hash algorithm". I think RSACryptoServiceProvider -might- still support RSA+MD4, but RSAOpenSsl doesn't).

From the assembly strong name perspective, we already recommend public sign for .NET Core projects, and don't know where in that doc stream anyone would find "if building for .NET Framework or .NET Standard (for .NET Framework) from [a RedHat-influenced distro], things get complicated".

So, I'm not opposed to documentation, just can't think of where it'd go and how to explain the problem or solution in an approachable manner 😄.

@akoeplinger
Copy link
Member

I'm curious which part of the .NET 6 build requires real signing (the log file linked in the original post isn't available anymore). Presumably we should still fix that one at least to use public sign?

@bartonjs
Copy link
Member

Any library that can encounter a strongname check on .NET Framework probably needs to be strong name signed, so that's potentially anything in the project tree that compiles for .NET Framework or .NET Standard (and excluding anything that compiles against a .NET Core/5+ TFM).

But that's really only true for an official distribution channel that can realistically end up on .NET Framework where it might encounter an SN check. I don't think there's anything that builds out of dotnet/* that expects to end up in a realistic SN-relevant scenario where Microsoft doesn't have the official build and distribution channel. So that means that (e.g.) Red Hat building dotnet/* using public signing, since the output of those builds is generally expected only to be for the shared runtime for Red Hat-influenced Linux distros.

The main SN-relevant scenario on .NET Framework is installing an assembly in the GAC. Apps using local copies of DLLs from NuGet or whatever aren't SN-relevant (OK, I think there's a regkey to make .NET Framework SN-check all assembly loads, but it's almost definitely not the default). So "we" (Microsoft builds) have to do real-signing (particularly for assemblies that have in the past), but it shouldn't come up much for anyone else.

@omajid
Copy link
Member Author

omajid commented Mar 28, 2022

I'm curious which part of the .NET 6 build requires real signing (the log file linked in the original post isn't available anymore). Presumably we should still fix that one at least to use public sign?

I am hitting that in source-build-reference-packages:

    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error : Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:03000098:digital envelope routines::invalid digest [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build) Unhandled exception. Interop+Crypto+OpenSslCryptographicException: error:03000098:digital envelope routines::invalid digest
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Interop.Crypto.RsaSignHash(SafeEvpPKeyHandle pkey, RSASignaturePaddingMode paddingMode, IntPtr digestAlgorithm, ReadOnlySpan`1 hash, Span`1 destination) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Interop.Crypto.RsaSignHash(SafeEvpPKeyHandle pkey, RSASignaturePaddingMode paddingMode, IntPtr digestAlgorithm, ReadOnlySpan`1 hash, Span`1 destination)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.TrySignHash(ReadOnlySpan`1 hash, Span`1 destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, Boolean allocateSignature, Int32& bytesWritten, Byte[]& signature) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.TrySignHash(ReadOnlySpan`1 hash, Span`1 destination, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding, Boolean allocateSignature, Int32& bytesWritten, Byte[%5D& signature)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.SignHash(Byte[] hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at System.Security.Cryptography.RSAImplementation.RSAOpenSsl.SignHash(Byte[%5D hash, HashAlgorithmName hashAlgorithm, RSASignaturePadding padding)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.SigningUtilities.CalculateRsaSignature(IEnumerable`1 content, RSAParameters privateKey) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.SigningUtilities.CalculateRsaSignature(IEnumerable`1 content, RSAParameters privateKey)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.DesktopStrongNameProvider.<>c__DisplayClass12_0.<SignBuilder>b__0(IEnumerable`1 content) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.DesktopStrongNameProvider.<>c__DisplayClass12_0.<SignBuilder>b__0(IEnumerable`1 content)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at System.Reflection.PortableExecutable.PEBuilder.Sign(BlobBuilder peImage, Blob strongNameSignatureFixup, Func`2 signatureProvider) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at System.Reflection.PortableExecutable.PEBuilder.Sign(BlobBuilder peImage, Blob strongNameSignatureFixup, Func`2 signatureProvider)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at System.Reflection.PortableExecutable.ManagedPEBuilder.Sign(BlobBuilder peImage, Func`2 signatureProvider) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at System.Reflection.PortableExecutable.ManagedPEBuilder.Sign(BlobBuilder peImage, Func`2 signatureProvider)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.DesktopStrongNameProvider.SignBuilder(ExtendedPEBuilder peBuilder, BlobBuilder peBlob, RSAParameters privateKey) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.DesktopStrongNameProvider.SignBuilder(ExtendedPEBuilder peBuilder, BlobBuilder peBlob, RSAParameters privateKey)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.Cci.PeWriter.WritePeToStream(EmitContext context, CommonMessageProvider messageProvider, Func`1 getPeStream, Func`1 getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, String pdbPathOpt, Boolean metadataOnly, Boolean isDeterministic, Boolean emitTestCoverageData, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.Cci.PeWriter.WritePeToStream(EmitContext context, CommonMessageProvider messageProvider, Func`1 getPeStream, Func`1 getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, String pdbPathOpt, Boolean metadataOnly, Boolean isDeterministic, Boolean emitTestCoverageData, Nullable`1 privateKeyOpt, CancellationToken cancellationToken)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.Compilation.SerializePeToStream(CommonPEModuleBuilder moduleBeingBuilt, DiagnosticBag metadataDiagnostics, CommonMessageProvider messageProvider, Func`1 getPeStream, Func`1 getMetadataPeStreamOpt, Func`1 getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, String pdbPathOpt, RebuildData rebuildData, Boolean metadataOnly, Boolean includePrivateMembers, Boolean isDeterministic, Boolean emitTestCoverageData, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.Compilation.SerializePeToStream(CommonPEModuleBuilder moduleBeingBuilt, DiagnosticBag metadataDiagnostics, CommonMessageProvider messageProvider, Func`1 getPeStream, Func`1 getMetadataPeStreamOpt, Func`1 getPortablePdbStreamOpt, PdbWriter nativePdbWriterOpt, String pdbPathOpt, RebuildData rebuildData, Boolean metadataOnly, Boolean includePrivateMembers, Boolean isDeterministic, Boolean emitTestCoverageData, Nullable`1 privateKeyOpt, CancellationToken cancellationToken)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.Compilation.SerializeToPeStream(CommonPEModuleBuilder moduleBeingBuilt, EmitStreamProvider peStreamProvider, EmitStreamProvider metadataPEStreamProvider, EmitStreamProvider pdbStreamProvider, RebuildData rebuildData, Func`2 testSymWriterFactory, DiagnosticBag diagnostics, EmitOptions emitOptions, Nullable`1 privateKeyOpt, CancellationToken cancellationToken) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.Compilation.SerializeToPeStream(CommonPEModuleBuilder moduleBeingBuilt, EmitStreamProvider peStreamProvider, EmitStreamProvider metadataPEStreamProvider, EmitStreamProvider pdbStreamProvider, RebuildData rebuildData, Func`2 testSymWriterFactory, DiagnosticBag diagnostics, EmitOptions emitOptions, Nullable`1 privateKeyOpt, CancellationToken cancellationToken)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CommonCompiler.CompileAndEmit(TouchedFileLogger touchedFilesLogger, Compilation& compilation, ImmutableArray`1 analyzers, ImmutableArray`1 generators, ImmutableArray`1 additionalTextFiles, AnalyzerConfigSet analyzerConfigSet, ImmutableArray`1 sourceFileAnalyzerConfigOptions, ImmutableArray`1 embeddedTexts, DiagnosticBag diagnostics, CancellationToken cancellationToken, CancellationTokenSource& analyzerCts, Boolean& reportAnalyzer, AnalyzerDriver& analyzerDriver) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CommonCompiler.CompileAndEmit(TouchedFileLogger touchedFilesLogger, Compilation& compilation, ImmutableArray`1 analyzers, ImmutableArray`1 generators, ImmutableArray`1 additionalTextFiles, AnalyzerConfigSet analyzerConfigSet, ImmutableArray`1 sourceFileAnalyzerConfigOptions, ImmutableArray`1 embeddedTexts, DiagnosticBag diagnostics, CancellationToken cancellationToken, CancellationTokenSource& analyzerCts, Boolean& reportAnalyzer, AnalyzerDriver& analyzerDriver)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CommonCompiler.RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CommonCompiler.RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, CancellationToken cancellationToken)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CommonCompiler.Run(TextWriter consoleOutput, CancellationToken cancellationToken) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CommonCompiler.Run(TextWriter consoleOutput, CancellationToken cancellationToken)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.<>c__DisplayClass1_0.<Run>b__0(TextWriter tw) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.<>c__DisplayClass1_0.<Run>b__0(TextWriter tw)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CommandLine.ConsoleUtil.RunWithUtf8Output[T](Boolean utf8Output, TextWriter textWriter, Func`2 func) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CommandLine.ConsoleUtil.RunWithUtf8Output[T%5D(Boolean utf8Output, TextWriter textWriter, Func`2 func)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.Run(String[] args, BuildPaths buildPaths, TextWriter textWriter, IAnalyzerAssemblyLoader analyzerLoader) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.Run(String[%5D args, BuildPaths buildPaths, TextWriter textWriter, IAnalyzerAssemblyLoader analyzerLoader)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CommandLine.BuildClient.RunCompilation(IEnumerable`1 originalArguments, BuildPaths buildPaths, TextWriter textWriter, String pipeName) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CommandLine.BuildClient.RunCompilation(IEnumerable`1 originalArguments, BuildPaths buildPaths, TextWriter textWriter, String pipeName)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CommandLine.BuildClient.Run(IEnumerable`1 arguments, RequestLanguage language, CompileFunc compileFunc, CompileOnServerFunc compileOnServerFunc) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CommandLine.BuildClient.Run(IEnumerable`1 arguments, RequestLanguage language, CompileFunc compileFunc, CompileOnServerFunc compileOnServerFunc)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Program.MainCore(String[] args) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CSharp.CommandLine.Program.MainCore(String[%5D args)
    /builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets(75,5): error :    at Microsoft.CodeAnalysis.CSharp.CommandLine.Program.Main(String[] args) [/builddir/build/BUILD/dotnet-v6.0.102/src/source-build-reference-packages.71a327c277a022d15af3d103c0796620ecd40471/artifacts/source-build/self/src/src/referencePackages/src/microsoft.bcl.asyncinterfaces/5.0.0/Microsoft.Bcl.AsyncInterfaces.5.0.0.csproj]
    ##vso[task.logissue type=error;sourcepath=/builddir/build/BUILD/dotnet-v6.0.102/previously-built-dotnet/sdk/6.0.102/Roslyn/Microsoft.CSharp.Core.targets;linenumber=75;columnnumber=5;code=;](NETCORE_ENGINEERING_TELEMETRY=Build)    at Microsoft.CodeAnalysis.CSharp.CommandLine.Program.Main(String[%5D args)

@tmds
Copy link
Member

tmds commented Apr 5, 2022

@bartonjs @vcsjones when we run dotnet/runtime tests there is no failure on RHEL 9. Does that mean this isn't covered by the tests?

@vcsjones
Copy link
Member

vcsjones commented Apr 5, 2022

We almost certainly have tests that would hit RSA+PKCS1+SHA1 signature condition, such as this one.

public void SignAndVerify_Roundtrip(string hashAlgorithm, RSAParameters rsaParameters)

Can you confirm if those tests ran?

@omajid
Copy link
Member Author

omajid commented Apr 5, 2022

In the xml results, I see:

<test name="System.Security.Cryptography.Rsa.Tests.SignVerify_Array.SignAndVerify_Roundtrip(hashAlgorithm: \&quot;MD5\&quot;, rsaParameters: System.Security.Cryptography.RSAParameters)" type="System.Security.Cryptography.Rsa.Tests.SignVerify_Array" method="SignAndVerify_Roundtrip" time="0.0071895" result="Pass" />
<test name="System.Security.Cryptography.Rsa.Tests.SignVerify_Array.SignAndVerify_Roundtrip(hashAlgorithm: \&quot;SHA1\&quot;, rsaParameters: System.Security.Cryptography.RSAParameters)" type="System.Security.Cryptography.Rsa.Tests.SignVerify_Array" method="SignAndVerify_Roundtrip" time="0.0068557" result="Pass" />
<test name="System.Security.Cryptography.Rsa.Tests.SignVerify_Array.SignAndVerify_Roundtrip(hashAlgorithm: \&quot;SHA256\&quot;, rsaParameters: System.Security.Cryptography.RSAParameters)" type="System.Security.Cryptography.Rsa.Tests.SignVerify_Array" method="SignAndVerify_Roundtrip" time="0.0072911" result="Pass" />
<test name="System.Security.Cryptography.Rsa.Tests.SignVerify_Array.SignAndVerify_Roundtrip(hashAlgorithm: \&quot;MD5\&quot;, rsaParameters: System.Security.Cryptography.RSAParameters)" type="System.Security.Cryptography.Rsa.Tests.SignVerify_Array" method="SignAndVerify_Roundtrip" time="0.0436004" result="Pass" />
<test name="System.Security.Cryptography.Rsa.Tests.SignVerify_Array.SignAndVerify_Roundtrip(hashAlgorithm: \&quot;SHA1\&quot;, rsaParameters: System.Security.Cryptography.RSAParameters)" type="System.Security.Cryptography.Rsa.Tests.SignVerify_Array" method="SignAndVerify_Roundtrip" time="0.0420614" result="Pass" />
<test name="System.Security.Cryptography.Rsa.Tests.SignVerify_Array.SignAndVerify_Roundtrip(hashAlgorithm: \&quot;SHA256\&quot;, rsaParameters: System.Security.Cryptography.RSAParameters)" type="System.Security.Cryptography.Rsa.Tests.SignVerify_Array" method="SignAndVerify_Roundtrip" time="0.042372" result="Pass" />
<test name="System.Security.Cryptography.Rsa.Tests.SignVerify_Array.SignAndVerify_Roundtrip(hashAlgorithm: \&quot;SHA384\&quot;, rsaParameters: System.Security.Cryptography.RSAParameters)" type="System.Security.Cryptography.Rsa.Tests.SignVerify_Array" method="SignAndVerify_Roundtrip" time="0.043085" result="Pass" />
<test name="System.Security.Cryptography.Rsa.Tests.SignVerify_Array.SignAndVerify_Roundtrip(hashAlgorithm: \&quot;SHA512\&quot;, rsaParameters: System.Security.Cryptography.RSAParameters)" type="System.Security.Cryptography.Rsa.Tests.SignVerify_Array" method="SignAndVerify_Roundtrip" time="0.0424903" result="Pass" />

😕

@tmds
Copy link
Member

tmds commented Apr 14, 2022

I don't know if this is a "problem" or not, but since .NET opts in to this strictness check whereas OpenSSL doesn't normally do this, you might see additional reports about .NET Failing to connect to HTTPS endpoints where the root certificate is RSA-SHA1 signed.

What happens when you use the url with wget/curl/...? Do they also use the 'strict' mode?

If they are happy with the certificate, .NET should be made less strict, and accept it certificate too.

@vcsjones
Copy link
Member

What happens when you use the url with wget/curl/...? Do they also use the 'strict' mode?

They do not appear to, no. We explicitly enable it here:

X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CHECK_SS_SIGNATURE);

.NET should be made less strict, and accept it certificate too.

I think the reason why this was added is because this is what Windows does. Windows checks the signature on self-signed certificates. So this was done so that X509 chain building is more consistent across platforms, as I understand it.

@bartonjs may want to weigh in on this one when he returns.

@tmds
Copy link
Member

tmds commented Apr 27, 2022

X509_STORE_CTX_set_flags(ctx, X509_V_FLAG_CHECK_SS_SIGNATURE);

@bartonjs can we drop this strict mode? It causes .NET to reject certificates on RHEL9 which are accepted by system tools like curl and wget.

@bartonjs
Copy link
Member

can we drop this strict mode?

No. It was added specifically because .NET on Windows was rejecting things that .NET on Linux wasn't. This is one of those places where I feel like ".NET is .NET" is the better compat answer.

@tmds
Copy link
Member

tmds commented Apr 27, 2022

No. It was added specifically because .NET on Windows was rejecting things that .NET on Linux wasn't. This is one of those places where I feel like ".NET is .NET" is the better compat answer.

That breaks .NET on RHEL9.
If the system considers the certificate secure, .NET shouldn't reject it for Windows-compatibilty sake.

@bartonjs
Copy link
Member

bartonjs commented Apr 27, 2022

That breaks .NET on RHEL9.

To be brutally honest: no, it doesn't. It reveals that RHEL9's change to OpenSSL is based on incorrect assumptions. RHEL9 broke experiences .NET on RHEL9, not this line of code. (RHEL made a change to this area, .NET didn't, ergo the active verb "break" can only be attributed to RHEL).

If the system considers the certificate secure, .NET shouldn't reject it for Windows-compatibilty sake.

That's a reasonable statement, and I think I'm willing to accept a PR that makes it true. However, that same PR cannot let corrupted self-signed certificates that were provided via chain.ChainPolicy.ExtraStore complete a chain build without reporting them as NotSignatureValid, or a chain build where a corrupted self-signed certificate is provided as the target certificate of the chain.

  • Chain build up to a system cert, cert is corrupted or uses a signature algorithm that the platform itself no longer considers valid yet the cert is still considered trustworthy for some reason: Pass is acceptable
  • Chain build up to a cert provided in chain.ChainPolicy.CustomTrustStore with the CustomRootTrust trust mode: I like this less. But, since that could be being done with the anchor selected from existing system trust (paring it down for pinning), I think "matches above" is the correct answer (and means we don't have to distinguish types of trust in this scenario).
  • Chain build up to a cert provided by ExtraStore, that isn't unified with a trusted certificate, that has a corrupted signature: NotSignatureValid.
  • Chain build up to a cert provided by ExtraStore, that isn't unified with a trusted certificate, that has an unsupported algorithm: NotSignatureValid.
  • Chain build of a corrupted self-issued cert, not trusted by the current chain context: Must report NotSignatureValid.
  • Chain build of a self-issued cert that uses an algorithm (etc), not trusted by the current chain context: Must report NotSignatureValid.
  • Chain builds against self-issued certs that are part of the trust context: I'm ambivalent here. On the one hand, I want to report "this is broken, yo"; on the other it's a little weird when popping up the chain goes from success to failure.

@jeffhandley jeffhandley added this to the 7.0.0 milestone Apr 27, 2022
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Apr 27, 2022
@tmds
Copy link
Member

tmds commented Apr 28, 2022

That's a reasonable statement, and I think I'm willing to accept a PR that makes it true. However, that same PR cannot let corrupted self-signed certificates that were provided via chain.ChainPolicy.ExtraStore complete a chain build without reporting them as NotSignatureValid, or a chain build where a corrupted self-signed certificate is provided as the target certificate of the chain.

Personally, I'd like .NET to be as close to validating certificates as the other tools on the system. Not more strict, and not less strict.

@bartonjs or @vcsjones, can one of you look into making this change? I can take a shot at it, but being largely unfamiliar with the subject, it will take me more time to understand the code, and figure out what changes are needed to match these requirements.

@omajid
Copy link
Member Author

omajid commented Apr 28, 2022

Fedora is also planning to disable SHA1 soon: https://fedoraproject.org/wiki/Changes/StrongCryptoSettings3Forewarning1

@bartonjs
Copy link
Member

Right now I don't have much availability... I'm focused on promised feature work before our "feature complete" preview (my portions are already a bit at-risk).

What's the urgency here / is it terrible if we don't fix it up before .NET 8?

Off the top of my head, what the PR needs to do, aside from make sure we have tests that cover the truth table above, is at/around

(where we have a WorkingChain but haven't built the elements yet), add something like

if (the last item has the OpenSSL equivalent to NotSignatureValid set)
{
    if (the chain didn't finish with PartialChain or UntrustedRootAuthority)
    {
        Clear(lastFlag, NotSignatureValid);
    }
}

That way we're describing under what situations we don't report the error, rather than trying to figure out the conditions where we need to circle back and decide if we need to perform the check.

(It may make more sense in BuildElements, since there the difference between "last" and "last error" stand out)

@tmds
Copy link
Member

tmds commented May 5, 2022

What's the urgency here / is it terrible if we don't fix it up before .NET 8?

We'd like this fixed before users are adopting .NET 6 on RHEL 9.
That means a fix+backport in the coming months.

Based on @vcsjones's input, I understand that as a workaround: we can source-build with OPENSSL_ENABLE_SHA1_SIGNATURES=1, and apply a single-line patch that removes the setting of X509_V_FLAG_CHECK_SS_SIGNATURE. This workaround would not meet the requirements set earlier.

We prefer an upstream fix over a workaround.
@vcsjones unless you are available to pick this up, I will take a shot at it.

@vcsjones
Copy link
Member

vcsjones commented May 5, 2022

@vcsjones unless you are available to pick this up, I will take a shot at it.

I will make an attempt but time box it. If it turns out to be more work than expected I may need to defer (my time spent in this repo is purely voluntary).

@tmds
Copy link
Member

tmds commented May 6, 2022

Thanks. Even if you can't finish it, your effort will give me a head start.

@tmds
Copy link
Member

tmds commented May 19, 2022

@vcsjones I assume you didn't find time for this. I'll give it a shot next week.

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label May 23, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label May 25, 2022
@tmds
Copy link
Member

tmds commented May 26, 2022

There are still two on-going tasks related to this:

  • update runtime tests so they pass on RHEL9
  • update the build on all source-built repos so they work without setting OPENSSL_ENABLE_SHA1_SIGNATURES=1

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants