When running in FIPS mode, OpenSSL 3 default properties should contain `fips=1`.
Describe the bug
When the kernel is running in FIPS mode, the OpenSSL 3 default properties doesn't contain fips=1, which makes EVP_default_properties_is_fips_enabled return false. The Go Microsoft toolchain needs to know if the FIPS mode is enabled or not to apply some additional logic on top of what's provided by OpenSSL.
To Reproduce Steps to reproduce the behavior:
- Set
OPENSSL_FORCE_FIPS_MODE=1to simulate kernel FIPS mode. - Compile and run a C program that calls
EVP_default_properties_is_fips_enabledand check if it returns true:
#include <stdio.h>
#include "openssl/evp.h"
int main(int ac, char **av)
{
int ret = EVP_default_properties_is_fips_enabled(NULL);
if (ret == 1)
printf("FIPS enabled\n");
else
printf("FIPS not enabled\n");
return 0;
}
Expected behavior
FIPS enabled
Real behavior
FIPS not enabled
Notes
There is a patch file that defines FIPS_mope as EVP_default_properties_is_fips_enabled: https://github.com/microsoft/azurelinux/blob/ba13b467104263b5740cdca3054ea5121d8160ab/SPECS/openssl/0008-Add-FIPS_mode-compatibility-macro.patch#L43C11-L43C20. I would expect fips=yes to be set when the kernel is running in FIPS mode.
@microsoft/golang-compiler
/cc @tobiasb-ms @christopherco
Any update on this?
I've discussed this issue with @tobiasb-ms offline. We agreed that this is something that should be handled on the caller site. AZL3 doesn't want to set the -fips=yes default property to support non-FIPS algorithms even when running in kernel FIPS mode. I agree with this approach, it's the caller responsibility to ensure their application is using the crypto APIs in a compliant manner.
Unfortunately, AFAIK there is no direct OpenSSL API that tells whether a provider is FIPS-capable or not, and I originally filled this issue because I need to know if the provider used by default is FIPS capable. I've work-arounded this issue by implementing the following (pseudo) code:
func fipsDefaultProvider() bool {
fipsProv := EVP_MD_get0_provider(EVP_MD_fetch(NULL, "SHA2-256", "-fips=yes")
defaultProv := EVP_MD_get0_provider(EVP_MD_fetch(NULL, "SHA2-256", NULL)
return fipsProv != NULL && fipsProv == defaultProv
}