dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.96k stars 4.65k forks source link

FIPS 140-2 certification status for .NET Core Crypto? #26037

Open SidShetye opened 6 years ago

SidShetye commented 6 years ago

@bartonjs @karelz : what's the FIPS 140-2 certification status for .NET Core Cryptography? On Windows it would seem that the standard windows FIPS certificate would simply pass through just as it does with .NET Framework. Can this be confirmed?

Is there any guidance on Mac/Linux? On linux if the system's OpenSSL binary is swapped out for an FIPS 140-2 openssl variant, will .net simply pick that automatically?

Govt use case. Thanks.

bartonjs commented 6 years ago

That's the idea, yeah. It's why we use system crypto libraries and don't bundle anything. I can't speak authoritatively, but I can speak to the shape of things. @leecow Do we have anything official here?


Unofficial statements

For .NET Core 2.0+ we use Security.framework on macOS; on Linux we use a system provided libcrypto.so.1.0.0 (and libssl.so.1.0.0), which may or may not be a FIPS build, and may or may not be certified for the specific distro version and hardware.

On macOS using RSAOpenSsl / DSAOpenSsl / ECDsaOpenSsl / ECDiffieHellmanOpenSsl use OpenSSL, not Security.framework, and so those may not be valid for use even when RSA.Create() and friends are.

It's up to the caller applications to ensure that only FIPS-approved algorithms are being used (e.g. we don't throw in .NET Core when you want to use MD5, but maybe you're doing Content-MD5 and not something to which FIPS applies).

adammulroy commented 6 years ago

Are there any hooks in place in the runtimeconfig.json or another location to ignore FIPS policy if it's enabled like there was in the .NET Framework?

See below for example on how we could ignore it in the exe.config before.

<configuration>  
    <runtime>  
        <enforceFIPSPolicy enabled="false"/>  
    </runtime>  
</configuration>  
bartonjs commented 6 years ago

@adammulroy No, because FIPS policy enforcement doesn't exist at all in .NET Core.

leecow commented 6 years ago

Nothing 'official' that would add to what Jeremy has already described.

SidShetye commented 6 years ago

Thanks guys, that helps for initial planning. Currently Trust Center and a few other places point to this technet article. Is there a plan to formally publish FIPS information in collaboration with Mike Grimm (Microsoft FIPS program) or Trust Center folks? Given the documentation heavy slant to the certification and compliance processes, I think it'll eventually be needed.

danmoseley commented 5 years ago

@bartonjs seems no work here is planned for 3.0 and this should move to Future?

bartonjs commented 5 years ago

Since we've also gotten rid of FIPS enforcement in net48 (by default) we probably want to update any documentation that mentions the enforceFIPSPolicy setting from netfx.

We possibly also need to write somewhere that our FIPSiness is inherited by the system FIPSiness for Core.

So we can call it 3.0 documentation or Future documentation, whatever you like. (Now that I've fixed it to say it's documentation)

SidShetye commented 5 years ago

@bartonjs @danmosemsft : Is there now authoritative, documented guidance on this from Microsoft? This has to be covered somewhere ... we really can’t be the first US Govt project using .NET Core.

Anyway, we now need this guidance soon.

danmoseley commented 5 years ago

@blowdart do you have anything here?

blowdart commented 5 years ago

@SidShetye What exactly do you need? I can get a page on the docs site saying .NET Core has no FIPS checks because we rely on the underlying OS. Or does it need something in formal wording somewhere central?

SidShetye commented 5 years ago

@blowdart Basically two audiences.

Compliance folks

Need authoritative documentation from Microsoft that we can point them towards. Items like:

1) That .NET Core doesn't perform any crypto whatsoever within itself - all operations are delegated to the underlying native OS cryptographic providers.

2) Captures steps necessary to get OS + .NET Core + App combination aligned for FIPS 140-2 compliance. I think this is not a done deal because OpenSSL is FIPS compliant through a supplemental binary called the "FIPS canister" which calling apps (= .NET S.S.C. ) have to init in a particular way. Specifically, the OpenSSL FIPS' Security policy , it states

The calling application enables FIPS mode by calling the FIPS_mode_set() function

It's unclear if .NET Core System.Security.Cryptography is actually doing this on Linux.

Sysadmins, Dev-Ops

An actionable, technical walk-through we can point them towards so they can positively verify that the OS + .NET Core + App code combination is indeed valid. Windows Server and Linux are important production targets. Given the varying sysadmin procedures across Linux, a representative snapshot covering just RHEL/CentOS and Ubuntu would be sufficient.

blowdart commented 5 years ago

Certified documentation is asking me to prove a negative in a way that;s legally binding.

This is going to take some research and lawyers.

As an aside FIPS on OpenSSL can be OS wide with an environment variable, that's the approach we expect people to take. We don't pass anything down at all, we defer to the operating system configuration.

SidShetye commented 5 years ago

@blowdart I'm not a lawyer, but it's just an official statement (vs for e.g. assuming additional liability during a new contract). So as long as there was reasonable diligence (vs for e.g. speculative assumptions or intentional negligence), it should fall in line with standard business error-and-omissions disclaimers.

I went ahead and removed the work 'certified' from my prev comment for clarity since only "FIPS-140-2 certification" will arise from the crypto providers and their NIST FIPS compliance certificates; not .NET Core crypto if it's indeed all pass-through. So what we'd need from Microsoft is just authoritative guidance formally documenting that pass-thru blessing by saying

I think this info is sprinkled across github comments and source; as .net core customers we need your help to compile it into concise, cohesive document that we can point our own customers to.

SidShetye commented 5 years ago

Also, the OPENSSL_FIPS environment variable you pointed to does indeed toggle it, thanks. Here is the console result when I quickly audited FIPS mode on CentOS 7.6 (md5 vs sha256)

[sid@lab-linux22 ~]$ rpm -q centos-release
centos-release-7-6.1810.2.el7.centos.x86_64
[sid@lab-linux22 ~]$ export OPENSSL_FIPS=1
[sid@lab-linux22 ~]$ openssl md5 .bashrc
Error setting digest md5
139991007758224:error:060800A3:digital envelope routines:EVP_DigestInit_ex:disabled for fips:digest.c:256:
[sid@lab-linux22 ~]$ openssl sha256 .bashrc
SHA256(.bashrc)= 898ed3bdcb749c665866ee2750ab50d7ac5da6b666546fcd952cfc4cbc0c33b4
[sid@lab-linux22 ~]$
tomato42 commented 4 years ago

Speaking with my Red Hat fedora on: The openssl package in CentOS is not FIPS certified. If a module is not listed on NIST CMVP page then it is not certified.

A correct use of FIPS module also requires for it to be used in Approved mode of operation, as specified in its Security Policy. For example, the certificate for RHEL-7 version of OpenSSL is 3538 and it's corresponding Security Policy. For this module, it's not sufficient to set the environment variable for it to considered to be working in Approved mode.

Also please note that the Security Policy specifies which interfaces are certified – not all interfaces have to be certified, and non-certified interfaces do not have to be disabled when the module is working in Approved mode. I'm noting that as the openssl md5 command does not use the approved interface in all versions of the library.

SidShetye commented 4 years ago

@tomato42 I understand your position as Red Hat. Red Hat's FIPS certification for RHEL applies to the entire OS above and beyond OpenSSL, into non-OpenSSL areas like ssh or dm-crypt etc. But you must also be aware that OpenSSL itself is independently FIPS certified (see certificate 2473 for example). This thread discusses only OpenSSL and it's consumers sitting up-stack (i.e. .NET Core Crypto).

@blowdart @bartonjs I ran into something through a customer conversation. There is a note in appendix C of the OpenSSL GIPS User Guide (emphasis mine):

The OPENSSLFIPS=1 environment variable enables FIPS mode for a openssl command_ generated from a FIPS capable OpenSSL distribution.

This gives the impression that openssl console commands (e.g. $ openssl sha256 somefile) are the only ones that fall into the FIPS mode and NOT openssl native library calls (which are EVP_** C calls IIRC). If that's the case then .NET crypto would need some init to enable FIPS mode. Which makes me wonder - how are all these recommendations given out to deploy .NET Core on Azure Government? Seems absolutely any USG system would need it's FIPS story sorted out. Or is every single USG + .NET Core customer using Windows Server and not RHEL or Linux?

Lastly but most importantly, can we please bound the resolution of this issue within a set timeline? It's been a hot potato problem for a while now, would appreciate it.

tomato42 commented 4 years ago

Still with fedora on: @SidShetye Sorry, it looks like I wasn't clear. Unfortunately, the FIPS landscape is complex, so I can't really speak in generalisations and remain truthful.

Red Hat's FIPS certification for RHEL applies to the entire OS above and beyond OpenSSL

No, RHEL as a complete OS is not certified. No version of RHEL was certified and even if we wanted to certify the whole OS it's unlikely we could, given the current rules of certification. Only specific modules in the RHEL OS were ever certified.

That being said, we do audit applications that we distribute and check if they use cryptographic algorithms from FIPS certified modules in a way that's consistent with their security policy. (Some people describe it as "FIPS compliance", but such usage of this term is not recognised by NIST and there is no certification process associated with it. There are also contradictory definitions of that term so I won't use it.)

But you must also be aware that OpenSSL itself is independently FIPS certified (see certificate 2473 for example).

Yes, I am aware that there is a FIPS certified module from the OpenSSL project and I'm aware of one also from SuSE for SLES (other modules may be available). But my point is that those are different modules. I have not studied them or their Security Policies, so I can't speak for them. But I do know that the behaviour of the FIPS module for OpenSSL in different RHEL versions is different. I also do know that the OpenSSL project's FIPS module is significantly different from the FIPS module for OpenSSL we ship in RHEL (modules with certificates #2473 and #3538 are significantly different, even if they both support the same version of OpenSSL library, the version 1.0.2).

OpenSSL library can use different FIPS modules and not all FIPS modules are the same.

This gives the impression that openssl console commands (e.g. $ openssl sha256 somefile) are the only ones that fall into the FIPS mode and NOT openssl native library calls (which are EVP_** C calls IIRC). If that's the case then .NET crypto would need some init to enable FIPS mode.

Now, I can't speak with authority on OpenSSL project's FIPS module (please consider it pure speculation and an unofficial statement on my part), but reading its Security Policy it looks like it's the application using OpenSSL that needs to enable FIPS mode (see step 6, page 26) in the module.

I can say that this is not a procedure that applications need to perform on RHEL. For RHEL-7, the applications do not have to perform any additional library calls, but the whole OS needs to be put into FIPS mode, see Chapter 8 of RHEL-7 Security Guide. But any software (be it 1st or 3rd party) running on RHEL still needs to follow the Security Policy of the specific cryptographic modules it uses.

SidShetye commented 4 years ago

@bartonjs From my previous comment and from the follow-up one by @tomato42, it appears .NET crypto should be issuing the FIPS_mode_set() and asserting the returned success (per the OpenSSL security policy on page 26, step 6). Red Hat appears to have altered this, but that's not the standard approach for OpenSSL which does require that additional step that no sysadmin can issue ahead of time.

@blowdart Your suggestion for the OPENSSL_FIPS environment variable only makes the openssl CLI command run in FIPS mode, not the actual OpenSSL library used by .net core. The .NET guidelines here says

The system administrator is responsible for configuring the FIPS compliance for an operating system.

But that's impossible for any sysadmin for almost all Linux + standard OpenSSL + FIPS module combinations without @bartonjs providing some hooks to execute FIPS_mode_set() at bootup. The only way this is possible is by using custom OpenSSL FIPS modules like RHEL, but means vendor lock-in.

Ask

Long story short, for future releases, we need a .NET Core Crypto API that in turn calls FIPS_mode_set() when running on Linux (and possibly a no-op on Windows and macOS)

arunswarnam commented 3 years ago

@SidShetye Thanks for bringing this up. We have a similar requirement. I see the issue is still open but I was curious to know if you found a way in .NET Core to enable FIPS mode in the underlying OS Crypto Provider and assert FIPS Mode has been enabled?

SidShetye commented 3 years ago

if you found a way in .NET Core to enable FIPS mode in the underlying OS Crypto Provider and assert FIPS Mode has been enabled?

@arunswarnam : Nopes :(

Right or wrong, I get the impression the .NET crypto team itself doesn't authoritatively understand how their architecture maps onto FIPS 140-2 requirements.

DemiMarie commented 3 years ago

if you found a way in .NET Core to enable FIPS mode in the underlying OS Crypto Provider and assert FIPS Mode has been enabled?

@arunswarnam : Nopes :(

Right or wrong, I get the impression the .NET crypto team itself doesn't authoritatively understand how their architecture maps onto FIPS 140-2 requirements.

I suspect the answer boils down to, “Use an operating system (such as RHEL) for which OpenSSL is FIPS-certified without any additional effort required on the part of the application.”. That matches my understanding of HashiCorp Vault’s position, which appears to be, “If you need to use FIPS 140-2 certified cryptography, you will need to provide an external implementation and configure Vault to use it.”.

zerovian commented 9 months ago

Adding my two cents here. We load and use .NET via hostfxr. We also statically link in OpenSSL for our own purposes (some stuff is .NET some isn't) and have the ability to force the statically linked copy to FIPS mode. Unfortunately, since it is statically linked it doesn't get shared with .NET. Instead .NET goes ahead and loads the system supplied version of OpenSSL (on linux anyway...on Windows it uses platform libraries). This leaves us with 2 different copies OpenSSL loaded into the application: one configured with FIPS, but the shared/.NET copy, not FIPS enabled.

We need at the very least the option for .NET to expose “[FIPS_mode_set](https://wiki.openssl.org/index.php/FIPS_mode_set())()” and check the result. This would be bare minimum.

DemiMarie commented 9 months ago

@zerovian have you considered using a container and dynamically linking to a certified OpenSSL? You can then call FIPS_mode_set() or equivalent from the native side before the runtime starts.

zerovian commented 9 months ago

Strictly containers is not an option in our world. Our customers deploy on both Linux and Windows,, bare metal, or containers, in cloud...whatever, their choice. Some customers require FIPS support, and having lack of support in .NET means they can't use .NET at all (which is an option), but that can often hobble their app, and they have to find workarounds.

Possible force loading OpenSSL ahead of time and setting it to FIPS mode before we try to load .NET may be an option.

DemiMarie commented 9 months ago

@zerovian Since you need this for a commercial product, I recommend either having your company implement FIPS 140-2 support in .NET, or pay a contractor to do it.