-
Notifications
You must be signed in to change notification settings - Fork 133
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
Add support for setting of a profile for a TPM 2 #716
Conversation
004ac8d
to
bbee00c
Compare
Pull Request Test Coverage Report for Build 4265
💛 - Coveralls |
cfa8445
to
83aa5c9
Compare
8ccee76
to
75852b1
Compare
a793593
to
60c0331
Compare
d32aaf9
to
d387c72
Compare
d387c72
to
376386d
Compare
ad63d13
to
ba16bc0
Compare
src/swtpm/tpmlib.c
Outdated
* enabled check whether any of the algorithms that the TPM 2 uses would need | ||
* OpenSSL FIPS mode to be disabled for the TPM 2 to work and then try to disable | ||
* it. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Disabling FIPS mode in openssl made sense for swtpm historically, since the hardcoded algorithm list prevents it from working at all.
Going forward though, I don't think we should keep that behaviour. Disabling FIPS mode in openssl is too big of a hammer. We were doing it to allow the blocked algorithms, but it has the secondary behaviour of turning off FIPS self-tests in all the non-blocked algorithms. IOW, even if the guest only uses the FIPS permitted algorithms, the TPM is not FIPS compliant due to all self-tests being disabled in openssl.
IMHO, now that we have algorithm configuribility, if someone has requested the TPM to have an algorithm set that is incompatible with FIPS mode, then I think we should refuse to start the TPM at all, so that the host admin immediately sees their incorrect configuration request, rather than have the TPM silently run in non-FIPS compliant mode.
Going further than that, I wonder if we have proactively self-test the supported algorithms in openssl in general. Regardless of what crypto-policy is enabled in openssl, we don't want to launch the TPM, if openssl is blocking one of the algorithms that it is configured to expose. At best that will result in the guest seeing the TPM in a failed state at runtime, which is harder to diagnose than if we refuse startup of swtpm entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IOW, even if the guest only uses the FIPS permitted algorithms, the TPM is not FIPS compliant due to all self-tests being disabled in openssl.
This FIPS thing is a problem. There's FIPS mode on the host where I remember running into inconsistencies on Fedora, CentOS etc. when enabling FIPS mode. Sometimes it seemed to not even enforce it or not disable the same algorithms across all machines (camellia, tdes, rsa-es, ecc keys smaller than 224bit). Then there's FIPS for the TPM 2 itself where it's not clear to me what needs to be done considering documents I have seen.
For example, the TPM itself is not FIPS compliant due to the algorithms it implements or how it uses them. There's an old FIPS guidance document here but I am not sure of its significance nor whether it is complete (from what I had seen elsewhere) or what changes it would require to the code: https://trustedcomputinggroup.org/resource/tcg-fips-140-2-guidance-for-tpm-2-0/
IMHO, now that we have algorithm configuribility, if someone has requested the TPM to have an algorithm set that is incompatible with FIPS mode, then I think we should refuse to start the TPM at all, so that the host admin immediately sees their incorrect configuration request, rather than have the TPM silently run in non-FIPS compliant mode.
Well, building a profile and submitting it from the level libvirt will not be easy for users either.
Ideally there would be a FIPS profile offered by the TPM 2, one that at least takes into consideration disabled algorithms on the host. It would of course have to function on all system.
Going further than that, I wonder if we have proactively self-test the supported algorithms in openssl in general.
Among the supported algorithms there must be a subset of algorithms that are disabled by FIPS mode. FIPS mode for 2024 and next few years should at least not mean something different between machines, so it should be possible to write a FIPS profile v1 that works on all current systems. That's why I was going to try at least offer a FIPS-on-host profile via libtpms.
I have a branch for libtpms to support FIPS profiles but I am quite a bit hesitant to merge this: https://github.com/stefanberger/libtpms/tree/stefanberger/fips-140-2%2B
First we would have to support FIPS mode on the host that disables some algorihms during runtime (e.g., signing a SHA1 while allowing signature verification with a sha1, camellia, tdes, rsa-es, etc). Then in the more difficult step there would be FIPS mode of the TPM 2 itself, if it can be done at all, that would build on top of it.
Thanks for looking at this. With FIPS I am not sure how to proceed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As you know, on Fedora / RHEL, everything related to crypto algorithm availability is controlled by the crypto-policies, which are in turn defined by the 'update-crypto-policies' tool. RHEL and Fedora usually have different policies at any given point in time, as RHEL tends to be more aggressive in blocking undesirable algorithms. eg it blocked SHA1 signatures many years before Fedora. Primarily the crypto policies tool generates config files for crypto libraries (openssl, gnutls, gcrypt, etc), but it can also generate config files for other programs. It just needs extension to teach it about the config format.
IOW, we could teach the crypto policies tool how to generate a policy in the libtpms format.
From a libvirt level, I could see us having a "policy" attribute on the '' element that gives a policy name to use for manufacturing. The valid choices could be the various built-in libtpms standard policies, plus a policy that is generated from the crypto-policies tool. Obviously that won't work if admins dynamically change crypto policies on an existing host, but in the case of FIPS, I would expect FIPS mode to be set when a host is first deployed, and never changed afterwards. If we took that approach, libtpms wouldn't have to define a FIPS policy itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obviously that won't work if admins dynamically change crypto policies on an existing host, but in the case of FIPS, I would expect FIPS mode to be set when a host is first deployed, and never changed afterwards. If we took that approach, libtpms wouldn't have to define a FIPS policy itself.
Though with FIPS being a standard I thought that we should be able to define a profile for it that works across all systems in 2024++. We just need to know the maximum set of algorithms we need to disable. Otherwise what would be the meaning of FIPS if it was configured differently on each host? Once a new FIPS version comes out we would have to create a new profile with more algorithms removed and the old one would not work anymore nor would the VM be able to start ever again on that host that would have presumably further restricted the set of algorithms that can be used on a FIPS-enabled host.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIPS isn't entirely precise. For example, it actually allows SHA1, but only allows use of SHA1 for signing for "legacy applications". RHEL-9's FIPS policy goes beyond this requirement, to fully block SHA1, though the change merged last week overrides that now for swtpm. Basically though, the Fedora/RHEL crypto maintainers would prefer if in the out of the box config, swtpm fully complied with currently configured crypto policy, and required a user opt-in for alternative configs. This is an inherently moving target.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIPS isn't entirely precise. For example, it actually allows SHA1, but only allows use of SHA1 for signing for "legacy applications".
I thought it would only disallow SHA1 for signing and not sign with keys < 2048bits but still allow signature verification.
We could define a FIPS profile without SHA1, so no legacy application support at all. If someone complains about this they could customize the custom profile to meet their requirements.
RHEL-9's FIPS policy goes beyond this requirement, to fully block SHA1, though the change merged last week overrides that now for swtpm.
This is an inherently moving target.
The problem with this is if it moves against existing profiles it will prevent VMs from starting. A problem is also a distro like Fedora where people just upgrade from one version to another and more algorithms restrictions will come their way and they wouldn't like it if their VMs didn't start anymore...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it would only disallow SHA1 for signing and not sign with keys < 2048bits but still allow signature verification.
IIUC the limits on SHA1 get defined in
http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar1.pdf
where it says
SHA-1 for digital signature generation:
SHA-1 may only be used for digital signature generation where specifically allowed by NIST protocol-specific guidance. For all other applications, SHA-1 shall not be used for digital signature generation.
SHA-1 for digital signature verification:
For digital signature verification, SHA-1 is allowed for legacy-use.
SHA-1 for non-digital signature applications:
For all other hash function applications, the use of SHA-1 is acceptable. The other applications include HMAC, Key Derivation Functions (KDFs), Random Bit Generation, and hash-only applications (e.g., hashing passwords and using SHA-1 to compute a checksum, such as the approved integrity technique specified in Section 4.6.1 of [FIPS 140]).
The problem with this is if it moves against existing profiles it will prevent VMs from starting. A problem is also a distro like Fedora where people just upgrade from one version to another and more algorithms restrictions will come their way and they wouldn't like it if their VMs didn't start anymore...
Yes, the upgrade path is a problem. The appropriate tradeoff is probably to strictly honour crypto-policies at time of manufacturing, but then force allow the selected algorithms at swtpm launch. The openssl config file override can likely to used to do the latter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the interest of making progress on this PR and being able to set a profile with swtpm/swtpm_setup I will remove the patches from it that are related to FIPS...
c396a71
to
34627bf
Compare
Libtpms v0.10 adds the TPMLIB_SetProfile call that swtpm needs to set a profile. Check whether the API call is available in the local libtpms installation. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Allow passing a JSON map as part of an option value in the format of --foo name={...},... Prior to this patch this would not have worked since the option values were broken apart around commas, which a map may also contain. Now, if a '{' is following the '=', the value is attempted to be parsed as a JSON map and the end of the map is searched considering possibly embedded maps. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
20094e3
to
d5986b5
Compare
Add support for the --profile option for a TPM 2. The 'name=' parameter allows a user to select a specific profile available in libtpms. The 'profile=' parameter allows a user to pass a JSON profile that must contain a name field with a profile known to libtpms. It may contain an algorithm field that has a comma-separated list of verbs with the names of algorithms that the TPM 2 is supposed to provide. The --profile option only has an effect the first time a TPM 2 is started since afterwards whenever the state of the TPM 2 is read, the profile found in the state is being used. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Display the new capability verb 'cmdarg-profile' indicating that the --profile option with the name= and profile= parameters is supported. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Print a list of names of profiles implemented by libtpms as part of the capabilities JSON. The profiles map will only be visible if libtpms v0.10 with the TPMLIB_SetProfile() API is used. swtpm socket --print-capabilities --tpm2| jq { "type": "swtpm", "features": [ [...] ], "profiles": { "names": [ "default-v1", "null", "custom" ], ... }, "version": "0.10.0" } Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add support for the --profile parameter that allows a user to select a profile for the TPM 2 instance. The profile parameter must be a string-formatted JSON map describing the profile to use. Resolves: stefanberger/libtpms#284 Resolves: #710 Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Print a list of names of profiles implemented by libtpms as part of the capabilities JSON. The profiles map will only be visible if libtpms v0.10 with the TPMLIB_SetProfile() API is used. swtpm_setup --print-capabilities --tpm2 | jq { "type": "swtpm_setup", "features": [ [...] ], "profiles": [ "default-v1", "null", "custom" ], "version": "0.10.0" } Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Implement test cases for swtpm_setup and swtpm exercising the --profile option. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add a test case for testing profiles across libtpms versions. For now only an instance with the NULL profile is being tested with the latest libtpms version and the state is then attempted to be used by libtpms v0.9. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Add support for --print-profiles option to print all profiles supported by libtpms. Usage: swtpm socket --tpm2 --print-profiles | jq Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
If the user did not provide the profile on the command line read the default profile from the swtpm_setup.conf configuration file. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
d5986b5
to
9e11191
Compare
This PR adds support for setting of profiles for a TPM 2 that restrict what algorithms are available to the TPM 2. It requires libtpms v0.10 with the profile support.
To setup an instance of swtpm with a specific profile one should use the
swtpm_setup
command like this:A profile can only be applied to a swtpm instance the very first time the instance is started or for as long as no state file exists in the tpmstate directory.
The availability of profiles can be queried from a running swtpm instance using swtpm_ioctl: