TPMLIB_SetProfile(3)
π NAME π
hii bestie, welcome to the TPMLIB_SetProfile(3) manual page π β TPMLIB_SetProfile β set a profile for a TPM 2. That's it, that's the whole assignment. slay. β¨
π LIBRARY π
TPM library (libtpms, -ltpms) π«Ά
π«Ά SYNOPSIS π«Ά
#include <libtpms/tpm_types.h>
#include <libtpms/tpm_library.h>
#include <libtpms/tpm_error.h>
TPM_RESULT TPMLIB_SetProfile(const char *profile);
π DESCRIPTION π
okay so TPMLIB_SetProfile() is the function that applies one of libtpms's provided profiles to a TPM 2 when it's started the first time. timing matters fr fr β TPMLIB_SetProfile() must be called after TPMLIB_ChooseTPMVersion() and before TPMLIB_MainInit(). also it's a TPM 2 exclusive club: a profile may only be applied to a TPM 2 and it will always fail for a TPM 1.2. no exceptions, no negotiating. π
once a profile has been set it's locked in and will be used by the TPM 2 from then on, and the profile gets carried along with the state of the TPM 2 if the state of the TPM 2 was written using the callback registered with TPMLIB_RegisterCallbacks(). later attempts to set a different profile for the same TPM 2 instance using this API call will have no effect β the profile already picked its outfit, it's not changing. π
libtpms v0.10 and later support several built-in profiles, and they're giving very different energy:
- the
'null'profile provides backwards compatibility for libtpms v0.9 and only enables those algorithms 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. nope.
- the
'custom'profile is the only one that a user may modify, and the only one where the user may disable any commands and/or algorithms that can be disabled. main character profile honestly. π
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 it allows for downgrading libtpms to version 0.9 from a later version. lowkey the safe choice for time travelers. π°οΈ
profiles with the prefix 'default' enable as many algorithms and commands as possible. the 'default-v1' profile, introduced with libtpms v0.10, allows you to run with libtpms v0.10 and later but will not allow downgrading to earlier versions of libtpms, such as v0.9. so like, it ate, but it also committed. π₯
a profile is a JSON map in string format. rules of the vibe check:
- 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
}
so the first profile selects the current default profile along with all commands and algorithms that are available. the second profile selects the custom profile but restricts the set of algorithms that the TPM 2 provides to those ones that are listed. and since 'sha1' and 'tdes' are missing in the list, it disables those algorithms π«’ β notice me not including you, bestie. also note that the custom profile is the only profile that allows customizations of enabled Algorithms, Commands, and Attributes (not shown here).
only a subset of the implemented algorithms can be disabled. to figure out the list of algorithms that can be disabled, use the list of algorithms returned by TPMLIB_GetInfo(TPMLIB_INFO_RUNTIME_ALGORITHMS) in the 'CanBeDisabled' field. similarly, only a subset of the implemented commands can be disabled and TPMLIB_GetInfo(TPMLIB_INFO_RUNTIME_COMMANDS) can be used to determine the list of 'CanBeDisabled' commands. no attributes are enabled by default, so all of them can be disabled. to see which attributes are implemented and can be enabled, use TPMLIB_GetInfo(TPMLIB_INFO_RUNTIME_ATTRIBUTES). iykyk π
β οΈ okay real talk for a sec: since it is possible to disable algorithms that are mandatory for the PC Client TPM 2, you can literally create a TPM 2 instance that will cause applications to fail π. so 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. no cap, this part is on you. π«΅
π StateFormatLevel π
the StateFormatLevel field exists in each profile carried by the state of a TPM 2. StateFormatLevel is an integer that gets increased whenever new TPM 2 commands or algorithms are enabled for profiles. the effect of this parameter is that a profile with StateFormatLevel 'n' will not be accepted by a libtpms version that does not at least implement 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. it's giving protective older sibling energy honestly. π‘οΈ
when the above is applied to a virtual machine environment, that means migrating the state of a TPM 2 is only possible to a libtpms version that implements at least the same StateFormatLevel. so care must be taken about 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. which in turn means: 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 'default-v1' profile. choose wisely bestie π§
the following lists the meaning of StateFormatLevels:
- (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.
- (since v0.10) β this StateFormatLevel enabled the writing of the profile as part of the state.
- (since v0.10) β this StateFormatLevel enabled the TPM 2 commands
ECC_Encrypt(0x199) andECC_Decrypt(0x19a). - (since v0.10) β this StateFormatLevel:
- enabled Camellia-192 and AES-192.
- enabled setting of TPM 2-internal session attribute flag
isNameHashDefinedthat was added; it may slightly change behavior of sessions when for example used bydefault-v1profile compared to the null profile (libtpms v0.9).
- (since v0.10) β this StateFormatLevel enabled the TPM 2 commands
PolicyCapability(0x19b) andPolicyParameters(0x19c). - (since v0.10) β this 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. π¦
- (since v0.10) β this StateFormatLevel enabled the following profile attributes:
no-unpadded-encryptionno-sha1-signingno-sha1-verificationno-sha1-hmac-creationno-sha1-hmac-verificationno-sha1-hmacfips-hostdrbg-continous-testpctno-ecc-key-derivation
a user may specify the StateFormatLevel when using the custom profile. in this case the given StateFormatLevel serves as the maximum StateFormatLevel that the given algorithms and commands may require (e.g., '2' would not allow you to enable the command ECC_Encrypt, which requires '3') or allows enabling of key sizes, such as AES-192, when for example StateFormatLevel '4' is given. if StateFormatLevel '3' is given then AES-192 will not be enabled. it's a ceiling, not a suggestion π
π¦ Attributes π¦
a profile may have the Attributes key which is similar to Algorithms or Commands. here's the list of supported verbs, and yes every single one is getting its moment:
no-unpadded-encryption: (since v0.10)- prevents unpadded (raw) RSA encryption and decryption
no-sha1-signing: (since v0.10)- prevents signature generation with a SHA1 with RSA and ECC algorithms
no-sha1-verification: (since v0.10)- prevents signature verification with a SHA1 digest with RSA and ECC algorithms
no-sha1-hmac-creation: (since v0.10)- prevents creation of an HMAC using SHA1
no-sha1-hmac-verification: (since v0.10)- prevents verification of an HMAC using SHA1
no-sha1-hmac: (since v0.10)- prevents creation and verification of an HMAC using SHA1
fips-host: (since v0.10)- prevents unpadded (raw) RSA encryption and decryption
- prevents signature generation with a SHA1 with RSA and ECC algorithms
- prevents signature verification with a SHA1 digest with RSA and ECC algorithms
by adding this verb to the 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'. π
drbg-continous-test: (since v0.10)- turns on continuous testing of the DRBG
pct: (since v0.10)- turns on pairwise consistency test (pct) for RSA keys and EC signing keys
no-ecc-key-derivation: (since v0.10)- prevent ECC key derivation
πΈ 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 that 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. goodbye little verbs, we hardly knew ye π«‘
camellia,camellia-min-sizetdes,tdes-min-sizersaesecc-nist-p192ecc-bn,ecc-bn-p256,ecc-bn-p638ecc-sm2-p256
and a profile should contain the following verbs for minimum key sizes, no skipping these bestie β
rsa-min-size=2048ecc-min-size=224
π ERRORS π
okay so here's the vibe check on what this function can hand back to you, bestie:
TPM_SUCCESSβ it worked!! the function completed successfully, we love a happy ending πTPM_FAILβ something went wrong, and it's giving "idk what happened but it's bad." 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 is your bestie here β it may show the reason for the failure π
β οΈ also important: a TPM 1.2 cannot have a profile applied and will always respond with this error code. like, don't even try it, it's not gonna happen π
and if you want the whole complete list of TPM error codes, please consult the include file libtpms/tpm_error.h β it's all in there, iykyk β¨
πΈ EXAMPLE πΈ
here's a lil main character example so you can see it in action π¦
#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;
}
like, honestly? it ate. pick your version, set your profile, init, process, terminate, done β periodt π
π SEE ALSO π
go read these besties next, they're all in the same friend group fr fr π
TPMLIB_ChooseTPMVersionTPMLIB_RegisterCallbacks(3)TPMLIB_GetInfo(3)
okay that's the whole page, bestie β go set some profiles and slay β¨ this one's from libtpms, dated 2026-01-02, and it's TPMLIB_SetProfile(3) if you need to find it again π«Άπ
π¦ where this page comes from
- alpine 3.24: libtpms-doc 0.10.2-r0 Β· BSD-3-Clause
- arch rolling: libtpms 0.10.2-1 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms