swtpm_ioctls(3)
π NAME π
okay bestie, welcome to swtpm_ioctls(3) β literally the page that explains the ioctl's of the CUSE TPM (swtpm_cuse) and the control commands used by the control channel over socket interface. π
β¨ SYNOPSIS β¨
#include <tpm_ioctl.h>
π DESCRIPTION π
The CUSE TPM implements an ioctl interface on the CUSE TPM's character device. These ioctl's are for out-of-band control of various TPM operations, like its initialization, resetting, and state migration. The control channel over TCP or UnixIO sockets uses control commands for these operations. π«Ά
The following is an enumeration of the supported ioctl's and control commands, along with the names of the data structure types. All ioctl's and control commands return a TPM error code in their response. Ioctl's are prefixed with PTM and control commands are prefixed with CMD. β¨
In case of the ioctl interface, the pointer to a command's data structure is passed as the 2nd parameter to the ioctl() function. The fields in the command's data structure are to be fill out in host endianness format. πΈ
In case of control commands, the command code must be encoded as a 4 byte integer preceding the command's data structure. Command code and data must be written in big endian format. π
π PTM_GET_CAPABILITY / CMD_GET_CAPABILITY, ptm_cap
This ioctl allows the caller to check which ioctl's are implemented by the CUSE TPM. The following is a list of capability flags that may be set upon return:
PTM_CAP_INIT(since v0.1) β ThePTM_INITioctl orCMD_INITcommand is supported.PTM_CAP_SHUTDOWN(since v0.1) β ThePTM_SHUTDOWNioctl orCMD_SHUTDOWNcommand is supported.PTM_CAP_GET_TPMESTABLISHED(since v0.1) β ThePTM_GET_TPMESTABLISHEDioctl orCMD_GET_TPMESTABLISHEDcommand is supported.PTM_CAP_SET_LOCALITY(since v0.1) β ThePTM_SET_LOCALITYioctl orCMD_SET_LOCALITYis supported.PTM_CAP_HASHING(since v0.1) β ThePTM_HASH_START,PTM_HASH_DATA, andPTM_HASH_ENDioctl's orCMD_HASH_START,CMD_HASH_DATA,CMD_HASH_ENDcommands are supported.PTM_CAP_CANCEL_TPM_CMD(since v0.1) β ThePTM_CANCEL_TPM_CMDioctl orCMD_CANCEL_TPM_CMDcommand is supported.PTM_CAP_STORE_VOLATILE(since v0.1) β ThePTM_STORE_VOLATILEioctl orCMD_STORE_VOLATILEcommand is supported.PTM_CAP_RESET_TPMESTABLISHED(since v0.1) β ThePTM_RESET_TPMESTABLISHEDioctl orCMD_RESET_TPMESTABLISHEDcommand is supported.PTM_CAP_GET_STATEBLOB(since v0.1) β ThePTM_GET_STATEBLOBioctl orCMD_GET_STATEBLOBcommand is supported.PTM_CAP_SET_STATEBLOB(since v0.1) β ThePTM_SET_STATEBLOBioctl orCMD_SET_STATEBLOBcommand is supported.PTM_CAP_STOP(since v0.1) β ThePTM_STOPioctl orCMD_STOPcommand is supported.PTM_CAP_GET_CONFIG(since v0.1) β ThePTM_GET_CONFIGioctl orCMD_GET_CONFIGcommand is supported.PTM_CAP_SET_DATAFD(since v0.1) β TheCMD_SET_DATAFDcommand is supported. This command only applies to UnixIO and there is no support forPTM_SET_DATAFD.PTM_CAP_SET_BUFFERSIZE(since v0.1) β ThePTM_SET_BUFFERSIZEioctl orCMD_SET_BUFFERSIZEcommand is supported.PTM_CAP_LOCK_STORAGE(since v0.8) β ThePTM_LOCK_STORAGEioctl orCMD_LOCK_STORAGEcommand is supported.
π¦ ptm_cap_n
The ptm_cap_n data structure can be used for non-CUSE swtpm and looks as follows:
struct ptm_cap_n {
union {
struct {
ptm_res tpm_result; /* will always be TPM_SUCCESS (0) */
uint32_t caps;
} resp; /* response */
} u;
};
π PTM_INIT / CMD_INIT, ptm_init
This ioctl must be used to initialize the TPM. It must be sent to the TPM before any TPM command is sent. π¨
The ptm_init data structure looks as follows:
struct ptm_init {
union {
struct {
uint32_t init_flags; /* see definitions below */
} req; /* request */
struct {
ptm_res tpm_result;
} resp; /* response */
} u;
};
The init_flags field in the request can be used to have the TPM delete the volatile state upon startup (PTM_INIT_FLAG_DELETE_VOLATILE).
A TPM result code is returned in the tpm_result field.
πΈ PTM_SHUTDOWN / CMD_SHUTDOWN, ptm_res
This ioctl allows a user to shut down the TPM.
A TPM result code is returned in ptm_res.
π«Ά PTM_GET_TPMESTABLISHED / CMD_GET_TPMESTABLISHED, ptm_est
This ioctl is used to check whether the TPM established flag is set.
The ptm_est data structure looks as follows:
struct ptm_est {
union {
struct {
ptm_res tpm_result;
unsigned char bit; /* TPM established bit */
} resp; /* response */
} u;
};
A TPM result code is returned in the tpm_result field.
The status of the TPM establishment flag is returned in the bit field.
π PTM_SET_LOCALITY / CMD_SET_LOCALITY, ptm_loc
This ioctl is used to set the current locality. All subsequent commands will be executed in this locality until the locality is changed.
The ptm_loc data structure looks as follows:
struct ptm_loc {
union {
struct {
uint8_t loc; /* locality to set */
} req; /* request */
struct {
ptm_res tpm_result;
} resp; /* response */
} u;
};
The locality number must be set in the request's loc field. Valid localities are in the range of 0 to 4.
A TPM result code is returned in the tpm_result field.
β PTM_HASH_START / CMD_HASH_START, ptm_res
This ioctl is used to start the hash operation that is typically initiated by writing into certain registers of locality 4 of the TPM Interface (TPM TIS). Subsequent write operations for transferring data must be done with the PTM_HASH_DATA ioctl.
A TPM result code is returned in ptm_res.
π¦ PTM_HASH_DATA / CMD_HASH_DATA, ptm_hdata
This command is used to transfer the data for the hash operation.
The ptm_hdata data structure looks as follows:
struct ptm_hdata {
union {
struct {
uint32_t length;
uint8_t data[4096];
} req; /* request */
struct {
ptm_res tpm_result;
} resp; /* response */
} u;
};
The length of the data is indicated in the length field with the data in the data field. Up to 4096 bytes can be transferred in one call.
A TPM result code is returned in the tpm_result field.
π§ PTM_HASH_END / CMD_HASH_END, ptm_res
This command is used to indicate the end of a hash operation that was started with the PTM_HASH_START ioctl.
A TPM result code is returned in ptm_res.
π₯ PTM_CANCEL_CMD / CMD_CANCEL_CMD, ptm_res
This command is used to cancel a TPM command.
A TPM result code is returned in ptm_res.
π PTM_STORE_VOLATILE / CMD_STORE_VOLATILE, ptm_res
This command is used to trigger the TPM to store the volatile state into a file.
A TPM result code is returned in ptm_res.
π PTM_RESET_ESTABLISHED / CMD_RESET_ESTABLISHED, ptm_reset_est
This command is used to reset the TPM's establishment flag.
The ptm_reset_est data structure looks as follows:
struct ptm_reset_est {
union {
struct {
uint8_t loc; /* locality to use */
} req; /* request */
struct {
ptm_res tpm_result;
} resp; /* response */
} u;
};
The locality in which the establishment flag is to be reset must be set in the loc field. Valid localities are in the range of 0 to 4.
A TPM result code is returned in the tpm_result field.
π PTM_GET_STATEBLOB / CMD_GET_STATEBLOB, ptm_getstate
This command is used to initiate the retrieval of one of the TPM's stateblobs.
The ptm_getstate data structure looks as follows:
struct ptm_getstate {
union {
struct {
uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */
uint32_t type; /* which blob to pull */
uint32_t offset; /* offset from where to read */
} req; /* request */
struct {
ptm_res tpm_result;
uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */
uint32_t totlength; /* total length that will be transferred */
uint32_t length; /* number of bytes in following buffer */
uint8_t data[PTM_STATE_BLOB_SIZE];
} resp; /* response */
} u;
};
In the request the state_flags field allows a user to set the PTM_STATE_FLAG_DECRYPT flag to retrieve decrypted TPM state in case the TPM's state was written in encrypted form.
The type field allows a user to choose one of the TPM's state blobs, and must be one of PTM_BLOB_TYPE_PERMANENT, PTM_BLOB_TYPE_VOLATILE, and PTM_BLOB_TYPE_SAVESTATE.
The offset field indicates at what offset to read the data from. Subsequent state transfers must advance the offset field to the next byte to be read. If the read() interface is used the offset will be advanced automatically.
The response returns a TPM error code in the tpm_result field.
The state_flags field in the response indicates whether the returned blob is encrypted.
The totlength field indicates the total length of the state blob.
The length field indicates the number of valid bytes in the data field.
If necessary, subsequent state blob transfers must be done using this ioctl or using the read() call on the file descriptor. All state must be transferred before the TPM will accept commands again. π¨
π« PTM_SET_STATEBLOB / CMD_SET_STATEBLOB, ptm_setstate
This command is used to transfer one of the TPM's stateblob to the TPM.
The ptm_setstate data structure looks as follows:
struct ptm_setstate {
union {
struct {
uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */
uint32_t type; /* which blob to set */
uint32_t length; /* length of the data;
use 0 on the first packet to
transfer using write() */
uint8_t data[PTM_STATE_BLOB_SIZE];
} req; /* request */
struct {
ptm_res tpm_result;
} resp; /* response */
} u;
};
okay so bestie, state_flags literally tells you whether the state you're handing over is encrypted or not. And if it is encrypted? π«Ά A migration key must have already been provided to the TPM, otherwise there's no way on earth it can decrypt that state. No key, no vibe check passing. π
the type field is your "which blob are we doing today" selector β it has to be exactly one of PTM_BLOB_TYPE_PERMANENT, PTM_BLOB_TYPE_VOLATILE, or PTM_BLOB_TYPE_SAVESTATE. Pick one, don't get cute with it. πΈ
the length field is how many bytes of state blob data are chilling in the data field. And here's the fun part π: if you wanna transfer that state blob using the write() call, you set length to 0 on the first packet. Iconic little protocol quirk, iykyk.
the response hands back a TPM error code in the tpm_result field. β¨
π PTM_STOP / CMD_STOP, ptm_res
this one stops the TPM. and before you panic β it's not the same as a TPM shut down! β The stopping of the TPM only halts its operations, it does not terminate the TPM process. Your little TPM buddy is just taking a nap π΄ β it can restart operation whenever with the PTM_INIT ioctl. main character energy: pause, don't exit. π
a TPM result code comes back in ptm_res.
π PTM_GET_CONFIG / CMD_GET_CONFIG, ptm_getconfig
this command retrieves the TPM's current configuration. slay, let's see what settings are giving. β¨
the ptm_getconfig data structure looks like this, no cap:
struct ptm_getconfig {
union {
struct {
ptm_res tpm_result;
uint32_t flags;
} resp; /* response */
} u;
};
a TPM result code is returned in the tpm_result field. π
and the flags field holds individual flags that tell you whether a file encryption key is in use (PTM_CONFIG_FLAG_FILE_KEY) and whether a migration key is in use (PTM_CONFIG_FLAG_MIGRATION_KEY). obsessed with a straightforward answer fr fr. π₯
π¦ CMD_SET_DATAFD, ptm_res
heads up bestie, this command is only implemented for the control channel over UnixIO socket. π It's used to establish the TPM command channel by transferring a socket file descriptor using the UnixIO socket's control channel and SCM_RIGHTS. very "sending you my location but make it filedescriptor". also peep sendmsg(2) and cmsg(3) for the whole story. π
a TPM result code is returned in ptm_res.
π§ CMD_SET_BUFFERSIZE, ptm_setbuffersize
this one lets a user set and query the buffer size that the TPM is using for input and output I/O buffers. multi-tasking queen π
the ptm_setbuffersize data structure looks like this:
struct ptm_setbuffersize {
union {
struct {
uint32_t buffersize; /* 0 to query for current buffer size */
} req; /* request */
struct {
ptm_res tpm_result;
uint32_t buffersize; /* buffer size in use */
uint32_t minsize; /* min. supported buffer size */
uint32_t maxsize; /* max. supported buffer size */
} resp; /* response */
} u;
};
so here's the tea π: if you set a 0 in the buffer size of the request, the response comes back with the buffer size that's currently in use β a little "just checking in" moment. Any other number will try to change the buffer size, but the TPM may adjust it to an allowed minimum or maximum, so don't take it personally. π The minimum and maximum supported buffer sizes are returned in the response, so you always know the range you're working with.
real talk: thebuffersizecan only be changed when the TPM is stopped. The currently usedbuffersizecan be read at any time though β reading is always free. π
π CMD_LOCK_STORAGE, ptm_lockstorage
locks the storage and retries a given number of times with 10ms delay in between. β³ Locking the storage may be necessary to do after the state of the TPM has been migrated out and the lock on the storage has been released when the 'savestate' blob was received β and now the storage should be locked again. basically you gave the key away, and now you need it back. π
the ptm_lockstorage data structure looks as follows:
struct ptm_lockstorage {
union {
struct {
uint32_t retries; /* number of retries */
} req; /* request */
struct {
ptm_res tpm_result;
} resp; /* response */
} u;
};
a TPM result code is returned in the tpm_result field. β¨
π SEE ALSO
okay that's the whole thing, bestie, you're officially fluent in swtpm_ioctls(3) π this page is from the swtpm source, dated 2026-08-19 β go forth and ioctl responsibly, love u, mwah ππ«Άβ¨
π¦ where this page comes from
- alpine 3.24: swtpm-doc 0.10.2-r0 Β· BSD-3-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms