mirror of
https://github.com/stefanberger/libtpms
synced 2025-08-25 19:32:02 +00:00

Add RuntimeAttribute 'fips-140-3' that restricts a TPM 2 following requirements of the FIPS-140-3 standard: - Prevents raw RSA encryption and decryption - Prevents SHA1 signature generation + verification - Prevents derivation of ECC keys from derivation parent and for creation of ephemeral keys - Performs a pairwise consistency test on RSA keys and ECC signing keys - Enables continous DRBG test Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
428 lines
12 KiB
Plaintext
428 lines
12 KiB
Plaintext
=head1 NAME
|
|
|
|
TPMLIB_SetProfile - Set a profile for a TPM 2
|
|
|
|
=head1 LIBRARY
|
|
|
|
TPM library (libtpms, -ltpms)
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
B<#include <libtpms/tpm_types.h>>
|
|
|
|
B<#include <libtpms/tpm_library.h>>
|
|
|
|
B<#include <libtpms/tpm_error.h>>
|
|
|
|
B<TPM_RESULT TPMLIB_SetProfile(const char *profile);>
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
B<TPMLIB_SetProfile()> is used to apply one of libtpms's provided profiles
|
|
to a TPM 2 when it is started the first time. B<TPMLIB_SetProfile()> must be
|
|
called after B<TPMLIB_ChooseTPMVersion()> and before B<TPMLIB_MainInit()>.
|
|
A profile may only be applied to a TPM 2 and will always fail for a TPM 1.2.
|
|
|
|
Once a profile has been set it will be used by the TPM 2 from then on and
|
|
the profile will be carried along with the state of the TPM 2 if the state
|
|
of the TPM 2 was written using the callback registered with
|
|
B<TPMLIB_RegisterCallbacks()>. Later attempts to set a different profile
|
|
for the same TPM 2 instance using this API call will have no effect.
|
|
|
|
Libtpms v0.10 and later support several built-in profiles. The 'null' profile
|
|
provides backwards compatibility for libtpms v0.9 and only enables those
|
|
algorithm and commands that were available at that version of libtpms.
|
|
The default profile enables all currently available commands and algorithms.
|
|
Neither one of these profiles allows any modifications by the user. The
|
|
'custom' profile is the only one that a user may modify and where the user
|
|
may disable any commands and/or algorithms that can be disabled.
|
|
|
|
If a NULL pointer is given as a profile then the 'null' profile will be
|
|
used and only commands and algorithms of libtpms v0.9 will be enabled.
|
|
The state of such a TPM 2 instance will be readable by the current version of
|
|
libtpms as well as later versions of libtpms and allow for downgrading
|
|
libtpms to version 0.9 from a later version.
|
|
|
|
Profiles with the prefix 'default' enable as many algorithms and commands
|
|
as possible. The 'default-v1' profile, introduced with libtpms v0.10, allows
|
|
to run with libtpms v0.10 and later but will not allow to downgrade to
|
|
earlir versions of libtpms, such as v0.9.
|
|
|
|
A profile is a JSON map in string format. It must contain the 'Name'
|
|
field with the name of a known profile. It may contain a field
|
|
'Algorithms' that holds a comma-separated list of algorithms (verbs) to
|
|
enable or the field 'Commands' that holds a comma-separated list of ranges
|
|
of command codes to enable.
|
|
|
|
The following are examples of TPM 2 profiles:
|
|
|
|
{"Name":"default-v1"}
|
|
|
|
{
|
|
"Name":"custom",
|
|
"Algorithms":"rsa,rsa-min-size=1024,tdes-min-size=128,hmac,aes,\
|
|
aes-min-size=128,mgf1,keyedhash,xor,sha256,sha384,\
|
|
sha512,null,rsassa,rsaes,rsapss,oaep,ecdsa,ecdh,ecdaa,\
|
|
sm2,ecschnorr,ecmqv,kdf1-sp800-56a,kdf2,kdf1-sp800-108,\
|
|
ecc,ecc-min-size=192,ecc-nist,ecc-nb,symcipher,camellia,\
|
|
camellia-min-size=128,cmac,ctr,ofb,cbc,cfb,ecb",
|
|
"StateFormatLevel":2
|
|
}
|
|
|
|
The first profile selects the current default profile along with all
|
|
commands and algorithms that are available.
|
|
The second profile selects the I<custom> profile but restricts the
|
|
set of algorithms that the TPM 2 provides to those ones that are listed.
|
|
Since 'sha1' and 'tdes' are missing in the list, it disables those algorithms.
|
|
Note that the I<custom> profile is the only profile that allows customizations
|
|
of enabled Algorthms and Commands.
|
|
|
|
Only a subset of the implemented algorithms can be disabled. To determine
|
|
the list of algorithms that can be disabled, use the list of algorithms
|
|
return by I<TPMLIB_GetInfo(TPMLIB_INFO_RUNTIME_ALGORITHMS)> in the
|
|
'CanBeDisabled' field. Similarly, only a subset of the implemented commands
|
|
can be disabled and I<TPMLIB_GetInfo(TPMLIB_INFO_RUNTIME_COMMANDS)> can
|
|
be used to determine the list of 'CanBeDisabled' commands.
|
|
|
|
Since it is possible to disable algorithms that are mandatory for the
|
|
PC client TPM 2 one can create a TPM 2 instance that will cause
|
|
applications to fail. Therefore, it is necessary to carefully select which
|
|
algorithms to disable following the requirements of applications that will
|
|
be used. At the same time the choice of enabled commands is important
|
|
so that algorithms that are enabled can actually be used with the set
|
|
of enabled commands and applications do not fail unexpectedly because of
|
|
disabled commands. Therefore, determining the list of algorithms and
|
|
commands to enable and disable is left to the user.
|
|
|
|
=head1 StateFormatLevel
|
|
|
|
The I<StateFormatLevel> field exists in each profile carried by the
|
|
state of a TPM 2. The I<StateFormatLevel> is an integer that is increased
|
|
whenever new TPM 2 commands or algorithms are enabled for profiles. The effect
|
|
of this parameter is that a profile with I<StateFormatLevel> 'n' will not be
|
|
accepted by a libtpms version that does not at least implement
|
|
I<StateFormatLevel> 'n'. This prevents applications that may have used any newly
|
|
enabled algorithms or commands from failing because they try to use them
|
|
again with a TPM 2 from a libtpms version that does not support them.
|
|
|
|
When the above is applied to a virtual machine environment then this means that
|
|
migrating the state of a TPM 2 is only possible to a libtpms version that
|
|
implements at least the same StateFormatLevel. Therefore, care must be taken
|
|
which profile is chosen so that the profile's StateFormatLevel does not
|
|
become the obstacle for migrating the TPM state between different versions
|
|
of libtpms. This in turn means that in an environment where older libtpms
|
|
versions exist, which may be a target for migration, then the oldest
|
|
libtpms version's supported profile should be chosen. If libtpms v0.9
|
|
exists then this should be the 'null' profile, for libtpms v0.10 this can
|
|
be the the 'default-v1' profile.
|
|
|
|
The following lists the meaning of I<StateFormatLevel>s:
|
|
|
|
=over 4
|
|
|
|
=item 1: (since v0.10)
|
|
|
|
This <StateFormatLevel> is reserved for the null profile. Only algorithms
|
|
and commands supported by libtpms v0.9 are enabled. To remain compatible
|
|
with libtpms v0.9 state format, the null profile will not be written as part
|
|
of the state.
|
|
|
|
=item 2: (since v0.10)
|
|
|
|
This I<StateFormatLevel> enabled the writing of the profile as part of the
|
|
state.
|
|
|
|
=item 3: (since v0.10)
|
|
|
|
This I<StateFormatLevel> enabled the TPM 2 commands ECC_Encrypt (0x199) and
|
|
ECC_Decrypt (0x19a).
|
|
|
|
=item 4: (since v0.10)
|
|
|
|
This I<StateFormatLevel>:
|
|
|
|
=over 2
|
|
|
|
=item * enabled Camellia-192 and AES-192.
|
|
|
|
=item * enabled setting of TPM 2-internal session attribute flag
|
|
isNameHashDefined that was added; it I<may> slightly change behavior
|
|
of sessions when for example used by default-v1 profile compared to
|
|
the null profile (libtpms v0.9).
|
|
|
|
=back
|
|
|
|
=item 5: (since v0.10)
|
|
|
|
This I<StateFormatLevel> enabled the TPM 2 commands PolicyCapability (0x19b)
|
|
and PolicyParameters (0x19c).
|
|
|
|
=item 6: (since v0.10)
|
|
|
|
This I<StateFormatLevel> made some internal changes to the marshalling and
|
|
unmarshalling code of an OBJECT. Only RSA key OBJECTS have the private
|
|
exponent field marshalled and the hierarchy field is also always marshalled
|
|
now. RSA key OBJECTs may be 4 bytes bigger while others are smaller now.
|
|
|
|
=item 7: (since v0.10)
|
|
|
|
This I<StateFormatLevel> enabled the I<fips-host> attribute.
|
|
|
|
=item 8: (since v0.10)
|
|
|
|
This I<StateFormatLevel> enabled the I<fips-140-3> attribute.
|
|
|
|
=back
|
|
|
|
A user may specify the I<StateFormatLevel> when using the I<custom> profile.
|
|
In this case the given I<StateFormatLevel> serves as the maximum
|
|
I<StateFormatLevel> that the given algorithms and commands may require
|
|
(e.g., '2' would not allow to enable the command ECC_Encrypt, which
|
|
requires '3') or allows to enable key sizes, such as AES-192, when for
|
|
example I<StateFormatLevel> '4' is given. If I<StateFormatLevel> '3'
|
|
is given then AES-192 will not be enabled.
|
|
|
|
=head1 Attributes
|
|
|
|
A profile may have the I<Attributes> key which is similar to I<Algorithms> or
|
|
I<Commands>. The following is a list of supported verbs:
|
|
|
|
=over 4
|
|
|
|
=item B<no-unpadded-encryption>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Prevents unpadded (raw) RSA encryption and decryption
|
|
|
|
=back
|
|
|
|
=item B<no-sha1-signing>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Prevents signature generation with a SHA1 with RSA and ECC
|
|
algorithms
|
|
|
|
=back
|
|
|
|
=item B<no-sha1-verification>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Prevents signature verification with a SHA1 digest with RSA and ECC
|
|
algorithms
|
|
|
|
=back
|
|
|
|
=item B<no-sha1-hmac-creation>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Prevents creation of an HMAC using SHA1
|
|
|
|
=back
|
|
|
|
=item B<no-sha1-hmac-verification>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Prevents verification of an HMAC using SHA1
|
|
|
|
=back
|
|
|
|
=item B<no-sha1-hmac>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Prevents creation and verification of an HMAC using SHA1
|
|
|
|
=back
|
|
|
|
=item B<fips-host>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Prevents unpadded (raw) RSA encryption and decryption
|
|
|
|
=item * Prevents signature generation with a SHA1 with RSA and ECC
|
|
algorithms
|
|
|
|
=item * Prevents signature verification with a SHA1 digest with RSA and ECC
|
|
algorithms
|
|
|
|
=back
|
|
|
|
By adding this verb to the I<Attributes> a TPM 2 can be run on a FIPS-enabled
|
|
host where the OpenSSL crypto library may restrict crypto algorithms as shown
|
|
above (reference is RHEL 9.4+, but varies by distro). Note that usage of this
|
|
verb does not make a TPM 2 instance compliant with FIPS-140. Also see the
|
|
section on 'FIPS mode on the host'.
|
|
|
|
=item B<drbg-continous-test>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Turns on continous testing of the DRBG
|
|
|
|
=back
|
|
|
|
=item B<pct>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Turns on pairwise consistency test (pct) for RSA keys and EC signing
|
|
keys
|
|
|
|
=back
|
|
|
|
=item B<no-ecc-key-derivation>: (since v0.10)
|
|
|
|
=over 2
|
|
|
|
=item * Prevent ECC key derivation
|
|
|
|
=back
|
|
|
|
=item B<fips-140-3>
|
|
|
|
This verb enables the following:
|
|
|
|
=over 2
|
|
|
|
=item * Prohibits raw RSA encryption and decryption
|
|
|
|
=item * Forbids SHA1 signature generation
|
|
|
|
=item * Forbids RSA < 2048 signature generation
|
|
|
|
=item * Forbids RSA < 2048 key generation
|
|
|
|
=item * Prevents derivation of ECC keys from derivation parent and for creation
|
|
of ephemeral keys
|
|
|
|
=item * Performs a pairwise consistency test on RSA keys and ECC signing keys
|
|
|
|
=item * Enables continous DRBG test
|
|
|
|
=back
|
|
|
|
Note that usage of the I<fips-140-3> verb does not translate into a claim that
|
|
the TPM 2 instance is FIPS-140-3 compliant but merely restricts the usage of
|
|
crypto algorithms by the TPM 2 following the above list.
|
|
|
|
=back
|
|
|
|
=head1 FIPS mode on the host
|
|
|
|
If FIPS mode is enabled on a host (reference is RHEL 9.4+) then the OpenSSL
|
|
crypto library will not be able to use certain algorithms. In this case the
|
|
following list of verbs should be omitted from a profile to avoid either
|
|
selftest failures or having to disable FIPS mode in the OpenSSL instance.
|
|
|
|
=over 2
|
|
|
|
=item * camellia, camellia-min-size
|
|
|
|
=item * tdes, tdes-min-size
|
|
|
|
=item * rsaes
|
|
|
|
=item * ecc-nist-p192
|
|
|
|
=item * ecc-bn, ecc-bn-p256, ecc-bn-p638
|
|
|
|
=item * ecc-sm2-p256
|
|
|
|
=back
|
|
|
|
A profile should contain the following verbs for minimum key sizes:
|
|
|
|
=over 2
|
|
|
|
=item * rsa-min-size=2048
|
|
|
|
=item * ecc-min-size=224
|
|
|
|
=back
|
|
|
|
=over 4
|
|
|
|
=back
|
|
|
|
=head1 ERRORS
|
|
|
|
=over 4
|
|
|
|
=item B<TPM_SUCCESS>
|
|
|
|
The function completed successfully.
|
|
|
|
=item B<TPM_FAIL>
|
|
|
|
A failure occurred. This may be due to a badly formatted JSON profile,
|
|
a missing field in the JSON profile, an unknown verb in the JSON profile,
|
|
or an out of memory error. The log file may show the reason for the
|
|
failure.
|
|
|
|
A TPM 1.2 cannot have a profile applied and will always respond with
|
|
this error code.
|
|
|
|
=back
|
|
|
|
For a complete list of TPM error codes please consult the include file
|
|
B<libtpms/tpm_error.h>
|
|
|
|
=head1 EXAMPLE
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <libtpms/tpm_types.h>
|
|
#include <libtpms/tpm_library.h>
|
|
#include <libtpms/tpm_error.h>
|
|
|
|
int main(void) {
|
|
TPM_RESULT res;
|
|
unsigned char *respbuffer = NULL;
|
|
uint32_t resp_size = 0;
|
|
uint32_t respbufsize = 0;
|
|
unsigned char *command;
|
|
uint32_t command_size;
|
|
|
|
[...]
|
|
|
|
if (TPMLIB_ChooseTPMVersion(TPMLIB_TPM_VERSION_2) != TPM_SUCCESS) {
|
|
fprintf(stderr, "Could not choose a TPM 2.\n");
|
|
return 1;
|
|
}
|
|
|
|
if (TPMLIB_SetProfile(NULL) != TPM_SUCCESS) {
|
|
fprintf(stderr, "Could not set the profile.\n");
|
|
return 1;
|
|
}
|
|
|
|
if (TPMLIB_MainInit() != TPM_SUCCESS) {
|
|
fprintf(stderr, "Could not start the TPM.\n");
|
|
return 1;
|
|
}
|
|
|
|
[...]
|
|
/* build TPM command */
|
|
[...]
|
|
|
|
res = TPMLIB_Process(&respbuffer, &resp_size,
|
|
&respbufsize,
|
|
command, command_size);
|
|
[...]
|
|
|
|
TPMLIB_Terminate();
|
|
|
|
return 0;
|
|
}
|
|
|
|
=head1 SEE ALSO
|
|
|
|
B<TPMLIB_ChooseTPMVersion>, B<TPMLIB_RegisterCallbacks>(3), B<TPMLIB_GetInfo>(3)
|
|
|
|
=cut
|