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
TPM 2.0 emulation silently fails on FIPS-enabled operating systems #703
Comments
|
If the TPM spec doesn't have the flexibility necessary to disable those algorithms, maybe we could completely disable the features that require them? |
|
The TPM 2 (reference) code does not support runtime-disablement of compile-time enabled algorithms. |
This is not so easy, since this would break the upgrade path of virtual machines and their attached TPMs. A (suspended) VM that has used the TPM with some crypto algorithm would expect that the same algorithm is available after start/resume of the VM again otherwise how would it be able to for example decrypt its data then if some crypto algorithm got disabled? |
If the new flags are local to the swtpm binary/process, and they are disabled by default, it shouldn't be a problem, as you'd have to change the VM definition to use them, right? |
What I meant with the above is that compile-time disablement of algorithms is not possible since this would prevent all existing swtpms to read their state or prevent software inside a VM to decrypt data that was previously encrypted with a now-disabled algorithm. If anything, the TPM 2 code would have to be changed to support runtime-disablement of algorithms and the set of disabled algorithms could only reasonably be set once at the initial creation of the TPM 2 and would have to be carried forward by the state of the TPM 2 from then on. That would be the only way to support disabling algorithms so that a VM can never use those algorithms and we don't get surprises that all of a sudden data cannot be decrypted anymore since algorithms have been disabled inside the TPM 2 because the crypto library disabled them but they were previously available and used. One wouldn't want that kind of a surprise. So when creating a VM one would have to decide which algorithms to disable and no algorithms that were left enabled could be disabled from then on by the crypto library because software inside the VM may have used these algorithms already and expects them to be there from then on. |
|
I've not tried to reproduce the scenario myself, but I strongly suspect that FIPS enablement is just one example of a more general problem. The crypto algorithms exposed by openssl are inherently dynamic. The algorithms available in the build environment cannot be assumed to be available in a runtime environment even ignoring FIPS. We have to expect there may be fewer available at runtime. Turning on FIPS is one thing that will influence what algorithms openssl reports. In RHEL / Fedora distros though there is also the global crypto policy in /etc/crypto-policies, which is a runtime per host configuration mechanism that might influence which algorithms openssl reports. IOW, restricting algorithms to only FIPS permitted algorithms at compile time, as well as causing upgrade issues, is also not likely to solve the more general problem. Ultimately I don't see how we can avoid selecting algorithms at the time of instantiating the vTPM, instead of at compile time. |
Yes, that should probably be a swtpm_setup feature, i.e. have a cmd line option to pick algorithms, or check all algorithms whenever they are actually enabled, or both. |
I was not thinking about a compile-time option, but a runtime one. |
No it wouldn't. swtpm_setup is run once when a VM is first provisioned to populate the VMs initial vTPM state. This state is preserved thereafter, for the lifetime of the VM, including across suspend/migrate/snapshot and so on. IOW swtpm_setup is exactly the right place to be selecting algorithms for a VM. |
|
Having runtime configurable algorithms (whether on the command line or via a config file) would also help me with testing. A lot of my TPM projects run test suites using a swtpm. The most common use case I'm thinking of is disabling sha1 to make sure all the test suites still pass when we start getting TPMs without that algorithm, but I'm sure there are other cases. I accept that once you start using a TPM with a particular algorithm configuration, you always have to keep exactly that config, which is why I suspect a file based runtime config would be better than a command line switch based one. |
|
Current solution to avoid libtpms failures is now here: PR #704 |
The set of disabled algorithms will have to become part of the permanent state of the TPM 2 to be able to stay with the TPM 2 instance and migrate along with it. |
Not necessarily, you could rely on the user (libvirt) to set the right arguments. Of course, it would be better if there was a check to avoid potential mis-configuration. |
Make swtpm_setup store the algorithm list (an enable list looks more robust to me than a disable list) next to the other state in the |
Can I edit this file then? Is it being migrated? |
|
And regarding an enabled list versus disabled list. It's not possible to disable some algorithms that are so essential to the TPM 2 to work, such as AES and possibly RSA. Actually one of the problems with runtime disabling the algorithms is figuring out in the TPM 2 code what side effects the disablement of each individual one has. And for that I would work with a disabled list. |
For those cases I think it would be acceptable for swtpm_setup to exit with a fatal error reporting that the host crypto config is lacking mandatory algorithms needed for TPM2. |
|
I have not been able to enable fips mode on Fedora 35 or 36 using |
The reason I think a enable list is more robust is that it takes out an indirection. A enable list specifies the list of algorithms required directly (and in case one of them isn't available you'll just throw an error and exit). With a disable list the algorithms supported by the swtpm is composed from multiple sources: compile time configuration (swtpm), runtime configuration (openssl), disable list. AES/RSA: I think they can either be added to the enable list unconditionally, or we define the enable list to only include algorithms which are actually optional. The former is probably more future-proof (i.e. works better in case a future tpm spec changes the list of mandatory algorithms). |
Does OpenSSL provide any means to determine which algorithms the FIPS mode has disabled, like introspection of some sort? This would avoid unnecessary trial and error to determine what can be used and what cannot be used. The difficulty with the TPM2 code is is that it is not prepared for runtime disablement of algorithms at all. So the only way this would work is to start out with a list of algorithms that are required to be enabled, which in the beginning would be all of them, and as one algorithm after the other is disable-able this list would shrink. From what I had seen in a CentOS9 environment that I put into FIPS mode it is only RSA-PSS signing scheme. I wonder whether that's it? Neither TDES nor Camellia were disabled there it seems. |
Note there's nothing particularly special about FIPS in terms of supported algorithms. FIPS is just one possible host OS crypto policy for selecting algorithms. Taking one of my Fedora 36 servers as an example, the initial crypto policy is 'DEFAULT' which allows a great many options I can change the crypto policy to 'FUTURE' which limits the host to a very restrictive set hoped to be immune to near-term crypto analysis attacks. We can see this limits openssl very significantly: I can pretend my machine userspace is in FIPS mode by just manually asking for the FIPS cipher set in the crypto policies (without actually turning on kernel FIPS support). With this we can get an indication of what openssl allows in FIPS mode, which is kind of half-way between the two above examples The general point is that it would be wrong to fixate on a particular set of FIPS ciphers, but rather need to just query openssl library to ask what is available in the currently running state. I'm not sure what specific openssl API is being invoked by the 'openssl ciphers' cli command to extra this cipher list though |
|
Thanks. I edited the policy of my F36 system to FIPS ( |
|
The same is true for Fedora 35 with OpenSSL 1.1. That's as if FIPS mode didn't disable anything the TPM 2 needs on these systems and we are fully compliant already. What am I missing? |
|
I had tested with this command line (as root and as non-root): Another test was running a swtpm in one terminal: In other terminal: Starting a VM (on Fedora 35) that had to create the initial state of the vTPM also worked just fine. From these tests I can only conclude that TPM 2 must be FIPS compliant. |
Ok, that's probably a sign that merely messing with crypto-policies is insufficient to properly simulate the effect of running in FIPS mode for purposes of testing swtpm. |
|
FYI: This is how TPM2 advertises its implemented algorithms: For example, the availability of crypto scheme TPM_ALG_OFB and symmetric algs TPM_ALG_TDES, TPM_ALG_AES, and TPM_ALG_CAMELLIA automatically implies that tdes-ofb, aes-ofb, and camellia-ofb are available and not one of them is missing, at least per the compile time options of the reference code. Test suites or programs that read the algorithm list may make these assumptions and I am not sure how they would react if these assumption were not to hold. I can certainly not speak about what programs do on windows for example. The point is though that I am not quite clear on how to disable algorithms during runtime, but the safer choice would be to simulate compile-time disablement, meaning that if 'ofb' is disabled tdes-ofb, aes-ofb, and camellia-ofb are all disable. Users don't give control over individual disablement of tes-ofb for example while leaving the other ones available. This is just one example and there are more with combinations of rsa and hashes and so on. |
Sounds good to me. I see no reason why compile-time configuration and runtime-configuration should behave in different ways. |
Also, the TPM 2 internally works with a bit vector of enabled algorithms, such as flags set for des or ctr for example. So, we wouldn't allow disabling of fine granularity like |
Hmmm, that could be troublesome, as I could certainly anticipate the need to disable based on key size |
I guess we need to get this right... The TPM2 internal-self test works with this above mentioned vector where each algorithm Id has a bit set. Keysizes don't matter there at all and test cases with different key sizes are enabled during compile time. We could filter out those test cases then. Also, ideally we would give a user fine-grained control over each algorithm that is implemented and provide a string like this here: Let's say the user only chooses the following: What does the TPM 2 now advertise in terms of implemented algorithms (as shown here)? |
|
Hmm, yes, this is a tricky problem. I don't know much about the TPM requirements, but perhaps the solution here varies depending on scenario ? IIRC, this whole discussion originated with a problem of self-tests failing due to missing algorithms, and it was trying to test all compiled in algorithms upfront, regardless of the OS needing to use it. How strict are the rules around self tests ? If we report support for 'aes' and 'ctr' do we need to self-test with all key sizes, or only one key size, or is it up to impl to decide ? eg can we report support for 'aes' and 'ctr', self test only aes-256-ctr, and report an error if the guest OS later tried to use aes-128-ctr that the guest OS is able to gracefully handle ? |
The TPM 2 reference code, which is the specification of the TPM 2, will cause a self-test to be run before an algorithms is used the first time or a full self test if instructed to do so, which the OS may do by sending a command to it. If the self test fails for an algorithm the TPM 2 will go into failure mode since something is broken. It's a crypto device after all, so it should probably react like this (or at least the spec defines that it will react like this). I guess what it comes down to for runtime-filtering is to define a language for the TPM 2 to filter-out algorithms. My current thinking would be to stick as closely as possibly to the defined algorithm Ids of the TPM 2 and their names and then maybe we need to add things like this: However, would this be correct to put aes,des, camellia, and sm4 under 'sym-key' and require a size >= 192 and this is equal strength for all of them? Or do we have to go to granularity like this? I don't know... But from the perspective of the TPM 2 code this latter here would be better.
I guess we would have to put additional filters into the code that skip over test cases with too small keys and just have them ignored. Other code paths where the user may want to use key a runtime-disabled key that is too small would then reject the operation. So from my perspective the problems are like this
|
Actually, this isn't true of Ken's TPM implementation. Each symmetric algorithm has a bits specifier and TDES is no different. You seem to have inherited his TDES_KEY_SIZES_BITS in your TpmProfile.h, so I think you could disable des-128 while keeping des-192 if you wanted. The same is true of AES: we can disable any of the 128, 192 or 256 key bit sizes individually. |
With an appropriate language we will be able to runtime-disable them and that's the only way of doing this. We cannot just completely disable algorithms and keysizes etc. anymore since applications inside VMs may already be using them and expect them to be there while these VMs are around. |
|
PR #704 resolved the issue for now by disabling FIPS mode in OpenSSL. Anything beyond that that requires profiles is a much bigger undertaking on the level of libtpms and swtpm. |
Describe the bug
On a FIPS-enabled machines, emulated TPM 2.0 devices fail their self-check and therefore are unusable.
To Reproduce
Steps to reproduce the behavior:
fips-mode-setup --enableand rebootvirt-manager)Expected behavior
The virtual machine can use the TPM device and the swtpm logs show no error
Desktop (please complete the following information):
Versions of relevant components
Log files
Additional context
The issue is discussed in more details there: https://bugzilla.redhat.com/show_bug.cgi?id=2090219
Some algorithms are just blocked by FIPS through openssl.
As mentioned in the bugzilla issue, adding options to swtpm for disabling those algorithms would be ideal (
--disable-camellia, --disable-algX, ...)The text was updated successfully, but these errors were encountered: