{"id":18346042,"url":"https://github.com/infineon/pkcs11-optiga-tpm","last_synced_at":"2025-04-06T08:32:53.684Z","repository":{"id":46058785,"uuid":"348637646","full_name":"Infineon/pkcs11-optiga-tpm","owner":"Infineon","description":"OPTIGA™ TPM-Based PKCS #11 Token Setup and User Guide","archived":false,"fork":false,"pushed_at":"2024-11-19T00:48:30.000Z","size":5422,"stargazers_count":5,"open_issues_count":0,"forks_count":3,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-03-21T21:02:37.506Z","etag":null,"topics":["pkcs11","raspberry-pi","security","tpm2"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Infineon.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-03-17T08:44:26.000Z","updated_at":"2024-11-19T00:48:34.000Z","dependencies_parsed_at":"2024-07-11T09:12:59.663Z","dependency_job_id":null,"html_url":"https://github.com/Infineon/pkcs11-optiga-tpm","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2Fpkcs11-optiga-tpm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2Fpkcs11-optiga-tpm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2Fpkcs11-optiga-tpm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Infineon%2Fpkcs11-optiga-tpm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Infineon","download_url":"https://codeload.github.com/Infineon/pkcs11-optiga-tpm/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247457567,"owners_count":20941902,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["pkcs11","raspberry-pi","security","tpm2"],"created_at":"2024-11-05T21:10:20.451Z","updated_at":"2025-04-06T08:32:53.381Z","avatar_url":"https://github.com/Infineon.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Github actions](https://github.com/infineon/pkcs11-optiga-tpm/actions/workflows/main.yml/badge.svg)](https://github.com/infineon/pkcs11-optiga-tpm/actions)\n\n# Introduction\n\nThis document outlines the process of integrating an OPTIGA™ TPM SLx 967x TPM2.0 to establish a TPM2-based PKCS #11 cryptographic token.\n\nPKCS #11, a Public-Key Cryptography Standard, establishes a standardized, platform-independent API for accessing cryptographic services from tokens, including hardware security modules (HSMs) and smart cards. This guide provides instructions for setting up a TPM2-based token.\n\n---\n\n# Table of Contents\n\n- **[Prerequisites](#prerequisites)**\n- **[Preparing the Environment](#preparing-the-environment)**\n    - **[One-Time Setup](#one-time-setup)**\n    - **[Recurring Setup](#recurring-setup)**\n- **[Backend Initialization](#backend-initialization)**\n    - **[ESYSDB (SQLite3) Backend](#esysdb-sqlite3-backend)**\n    - **[FAPI Backend](#fapi-backend)**\n- **[PKCS #11 Token Initialization](#pkcs-11-token-initialization)**\n    - **[pkcs11-tool from OpenSC](#pkcs11-tool-from-opensc)**\n    - **[tpm2_ptool from tpm2-pkcs11 (ESYSDB)](#tpm2_ptool-from-tpm2-pkcs11-esysdb)**\n        - **[Default Primary Key](#default-primary-key)**\n        - **[Custom Primary Key (Storage)](#custom-primary-key-storage)**\n        - **[Custom Primary Key (Platform)](#custom-primary-key-platform)**\n        - **[Link Existing Ordinary Keys (Storage)](#link-existing-ordinary-keys-storage)**\n        - **[Link Existing Ordinary Keys (Platform)](#link-existing-ordinary-keys-platform)**\n        - **[Import 3rd Party Keys and Certificates](#import-3rd-party-keys-and-certificates)**\n    - **[p11tool from GnuTLS](#p11tool-from-gnutls)**\n    - **[key_import from tpm2-pkcs11](#key_import-from-tpm2-pkcs11)**\n- **[Tools for Accessing PKCS #11 Tokens](#tools-for-accessing-pkcs-11-tokens)**\n    - **[pkcs11-tool from OpenSC](#pkcs11-tool-from-opensc-1)**\n    - **[libp11 from OpenSC (OpenSSL)](#libp11-from-opensc-openssl)**\n    - **[p11-kit](#p11-kit)**\n    - **[p11tool from GnuTLS](#p11tool-from-gnutls-1)**\n    - **[NSS Tools](#nss-tools)**\n- **[Housekeeping](#housekeeping)**\n    - **[Housekeeping (ESYSDB)](#housekeeping-esysdb)**\n    - **[Housekeeping (FAPI)](#housekeeping-fapi)**\n- **[GitHub Actions](#github-actions)**\n- **[License](#license)**\n\n---\n\n# Prerequisites\n\nThe integration guide has been CI tested for compatibility with the following platform and operating system. Please refer to section [GitHub Actions](#github-actions):\n\n- Platform: x86_64\n- Operating System: Ubuntu (22.04)\n\n---\n\n# Preparing the Environment\n\u003c!--section:setup-pt1--\u003e\n\n## One-Time Setup\n\nUpdates the package lists:\n```all\n$ sudo apt update\n```\n\nInstall generic packages:\n```all\n$ sudo apt -y install autoconf-archive libcmocka0 libcmocka-dev procps \\\n    iproute2 build-essential git pkg-config gcc libtool automake libssl-dev \\\n    uthash-dev autoconf doxygen libjson-c-dev libini-config-dev \\\n    libcurl4-openssl-dev uuid-dev pandoc acl libglib2.0-dev xxd \\\n    libsqlite3-dev libyaml-dev python3-pip libp11-kit-dev dbus opensc \\\n    meson libtasn1-bin libnss3-tools\n```\n\nInstall Python packages:\n```all\n$ python3 -m pip install --upgrade pip==24.0\n$ python3 -m pip install pyasn1_modules==0.2.8 cryptography==38.0.4 \\\n    pyyaml==6.0.1\n```\n\nInstall tpm2-tss:\n```all\n$ git clone https://github.com/tpm2-software/tpm2-tss ~/tpm2-tss\n$ cd ~/tpm2-tss\n$ git checkout 4.0.1\n$ ./bootstrap\n$ ./configure\n$ make -j\n$ sudo make install\n$ sudo ldconfig\n```\n\nInstall tpm2-tools:\n```all\n$ git clone https://github.com/tpm2-software/tpm2-tools ~/tpm2-tools\n$ cd ~/tpm2-tools\n$ git checkout 5.6\n$ ./bootstrap\n$ ./configure\n$ make -j\n$ sudo make install\n$ sudo ldconfig\n```\n\nInstall tpm2-abrmd:\n```all\n$ git clone https://github.com/tpm2-software/tpm2-abrmd ~/tpm2-abrmd\n$ cd ~/tpm2-abrmd\n$ git checkout 3.0.0\n$ ./bootstrap\n$ ./configure\n$ make -j\n$ sudo make install\n$ sudo ldconfig\n```\n\nInstall tpm2-pytss:\n```all\n$ git clone https://github.com/tpm2-software/tpm2-pytss ~/tpm2-pytss\n$ cd ~/tpm2-pytss\n$ git checkout 2.2.1\n$ python3 -m pip install -e .\n```\n\nDownload the tpm2-pkcs11:\n```all\n$ git clone https://github.com/tpm2-software/tpm2-pkcs11 ~/tpm2-pkcs11\n$ cd ~/tpm2-pkcs11\n$ git checkout 50a636bdb19220bf926cf6664e3084a315fe4480\n```\n\n\u003c!--section-end--\u003e\n\u003c!--section:setup-esysdb-install--\u003e\n\nInstall tpm2-pkcs11, two options are available:\n1. ESYSDB (SQLite3) as the PKCS #11 backend:\n    \u003e Disable the FAPI backend at build time by adding `--disable-fapi` to prevent unnecessary errors and warnings from the FAPI backend.\n    \u003e Optionally, disable FAPI error logging by setting `export TSS2_LOG=fapi+NONE`.\n    ```all\n    $ cd ~/tpm2-pkcs11\n    $ git clean -fxd\n    $ ./bootstrap\n    $ ./configure --disable-fapi\n    $ make -j\n    $ sudo make install\n    $ sudo ldconfig\n    ```\n\n\u003c!--section-end--\u003e\n\u003c!--section:setup-fapi-install--\u003e\n\n2. FAPI as the PKCS #11 backend:\n    ```all\n    $ cd ~/tpm2-pkcs11\n    $ git clean -fxd\n    $ ./bootstrap\n    $ ./configure\n    $ make -j\n    $ sudo make install\n    $ sudo ldconfig\n    ```\n\n\u003c!--section-end--\u003e\n\u003c!--section:setup-pt2--\u003e\n\nInstall libtpms-based TPM emulator:\n```all\n# Install dependencies\n$ sudo apt install -y dh-autoreconf libtasn1-6-dev net-tools \\\n    libgnutls28-dev expect gawk socat libfuse-dev libseccomp-dev \\\n    make libjson-glib-dev gnutls-bin\n\n# Install libtpms-devel\n$ git clone https://github.com/stefanberger/libtpms ~/libtpms\n$ cd ~/libtpms\n$ git checkout v0.9.6\n$ ./autogen.sh --with-tpm2 --with-openssl\n$ make -j\n$ sudo make install\n$ sudo ldconfig\n\n# Install Libtpms-based TPM emulator\n$ git clone https://github.com/stefanberger/swtpm ~/swtpm\n$ cd ~/swtpm\n$ git checkout v0.8.1\n$ ./autogen.sh --with-openssl --prefix=/usr\n$ make -j\n$ sudo make install\n$ sudo ldconfig\n```\n\nInstall the latest version of p11-kit to access a broader range of utilities. If installed via `apt install p11-kit`, only a limited set of subcommands is available:\n\u003e It is important to set the installation path correctly for p11-kit to be able to locate the PKCS #11 module configuration files (e.g., `tpm2_pkcs11.module` from tpm2-pkcs11), which are located in `/usr/share/p11-kit/modules/` in this setup.\n\u003e The PKCS #11 module configuration file is a file that contains a description of the PKCS #11 module and the path to the module (e.g., `libtpm2_pkcs11.so` from tpm2-pkcs11).\n```all\n$ git clone https://github.com/p11-glue/p11-kit -b 0.25.3 --depth=1 ~/p11-kit\n$ cd ~/p11-kit\n$ meson setup _build\n$ meson configure _build -Dprefix=/usr\n$ meson compile -C _build\n$ meson install -C _build\n$ sudo ldconfig\n```\n\nInstall the later version of [GnuTLS](https://www.gnutls.org/download.html) from the source:\n```all\n# Install dependencies\n$ sudo apt install -y wget\n\n# Download the source\n$ cd ~\n$ wget --no-verbose https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/gnutls-3.8.3.tar.xz\n$ tar -xf gnutls-3.8.3.tar.xz\n\n# Build and install the project\n$ cd ~/gnutls-3.8.3\n$ ./configure --with-included-unistring --disable-doc --disable-tests\n$ make -j\n$ sudo make install\n$ sudo ldconfig\n```\n\n\u003c!--\nInstall OpenSC:\n```\n# Install dependencies\n$ sudo apt install -y libpcsclite-dev\n\n# Install OpenSC\n$ git clone https://github.com/OpenSC/OpenSC ~/OpenSC\n$ cd ~/OpenSC\n$ git checkout 0.25.0\n$ ./bootstrap\n$ ./configure\n$ make -j\n$ sudo make install\n$ sudo ldconfig\n```\n--\u003e\n\n\u003c!--\nChange workspace:\n```all\n$ cd /tmp\n```\n--\u003e\n\n## Recurring Setup\n\nThis guide utilizes the session dbus. While using the system dbus is possible, it is not included in this documentation.\n\nStart a session dbus limited to the current login session:\n```all\n$ export DBUS_SESSION_BUS_ADDRESS=`dbus-daemon --session --print-address --fork`\n```\n\nLaunch the libtpms-based TPM emulator:\n```all\n$ export SWTPM_PATH=$(mktemp -d)\n\n# Create configuration files for swtpm_setup:\n# - ~/.config/swtpm_setup.conf\n# - ~/.config/swtpm-localca.conf\n#   This file specifies the location of the CA keys and certificates:\n#   - ~/.config/var/lib/swtpm-localca/*.pem\n# - ~/.config/swtpm-localca.options\n$ swtpm_setup --tpm2 --create-config-files overwrite,root\n\n# Initialize the swtpm\n$ swtpm_setup --tpm2 --config ~/.config/swtpm_setup.conf --tpm-state ${SWTPM_PATH} \\\n    --overwrite --create-ek-cert --create-platform-cert --write-ek-cert-files ${SWTPM_PATH}\n\n# Launch the swtpm\n$ swtpm socket --tpm2 --flags not-need-init --tpmstate dir=${SWTPM_PATH} \\\n    --server type=tcp,port=2321 --ctrl type=tcp,port=2322 \u0026\n$ sleep 5\n```\n\nLaunch the TPM Resource Manager daemon; it facilitates communication via session dbus and acts as an intermediary to the TPM emulator:\n```all\n$ tpm2-abrmd --allow-root --session --tcti=swtpm:host=127.0.0.1,port=2321 \u0026\n$ sleep 5\n```\n\nSpecifies the TCTI using an environment variable:\n```all\n$ export TPM2TOOLS_TCTI=\"tabrmd:bus_name=com.intel.tss2.Tabrmd,bus_type=session\"\n$ export TPM2_PKCS11_TCTI=\"tabrmd:bus_name=com.intel.tss2.Tabrmd,bus_type=session\"\n```\n\nFor convenience, use an alias to shorten the command:\n```all\n$ TPM2_P11_PATH=`pkg-config --variable=p11_module_path tpm2-pkcs11`\n$ alias pkcs11-tool-tpm2=\"pkcs11-tool --module ${TPM2_P11_PATH}/libtpm2_pkcs11.so\"\n$ alias tpm2_ptool=\"${HOME}/tpm2-pkcs11/tools/tpm2_ptool/tpm2_ptool.py\"\n$ alias\n```\n\nA simple test to verify that communication with the TPM is in order:\n```all\n$ tpm2_getrandom --hex 16\n```\n\n\u003c!--section-end--\u003e\n\n---\n\n# Backend Initialization\n\nTo meet the requirements of the PKCS #11 interface, additional metadata needs to be saved to a data \"store\". The provider of this \"store\" is referred to as the backend of the PKCS #11 token, which includes the following backend options:\n\n1. [ESYSDB (SQLite3)](#esysdb-sqlite3-backend)\n2. [FAPI](#fapi-backend)\n\n## ESYSDB (SQLite3) Backend\n\u003c!--section:backend-init-esysdb--\u003e\n\nClear the TPM:\n```all\n$ tpm2_clear -c p\n```\n\nSet the token store location:\n\u003e If not specified, the default path is set to `$HOME/.tpm2_pkcs11/tpm2_pkcs11.sqlite3`.\n```all\n$ export TPM2_PKCS11_STORE=$(mktemp -d)\n```\n\nLeaving the `TPM2_PKCS11_BACKEND` environment variable unset or setting it to `esysdb` defaults to the SQLite3 backend:\n```all\n$ export TPM2_PKCS11_BACKEND=\"esysdb\"\n```\n\n\u003c!--\nA workaround to prevent error \"FAPI_METADATA_DIR: unbound variable\" in test section \"tools-pkcs11-tool\".\n```all\n$ export FAPI_METADATA_DIR=$(mktemp -d)\n```\n--\u003e\n\n\u003c!--section-end--\u003e\n\n## FAPI Backend\n\u003c!--section:backend-init-fapi--\u003e\n\nSet the FAPI metadata store location:\n```all\n$ export FAPI_METADATA_DIR=$(mktemp -d)\n```\n\nInitialize a TPM 2.0-based PKCS#11 Token with the TPM Feature API (FAPI) as backend. First, is to provisions a FAPI instance.\n\nUpdate the FAPI configuration file at `/usr/local/etc/tpm2-tss/fapi-config.json`. The changes include:\n- Move all working directories to `${FAPI_METADATA_DIR}`.\n- The profile can be `P_RSA2048SHA256` or `P_ECCP256SHA256`. For better performance, `P_ECCP256SHA256` may be used.\n- Additionally, updating the TCTI parameter allows switching between hardware or a simulated TPM. If using a TPM simulator, it is also possible to set it to `ek_cert_less`.\n```all\n$ rm /usr/local/etc/tpm2-tss/fapi-config.json\n$ cat \u003e /usr/local/etc/tpm2-tss/fapi-config.json \u003c\u003c EOF\n$ {\n$     \"profile_name\": \"P_RSA2048SHA256\",\n$     \"profile_dir\": \"/usr/local/etc/tpm2-tss/fapi-profiles/\",\n$     \"user_dir\": \"${FAPI_METADATA_DIR}/user/keystore/\",\n$     \"system_dir\": \"${FAPI_METADATA_DIR}/system/keystore/\",\n$     \"tcti\": \"tabrmd:bus_name=com.intel.tss2.Tabrmd,bus_type=session\",\n$     \"ek_cert_less\": \"yes\",\n$     \"system_pcrs\" : [],\n$     \"log_dir\" : \"${FAPI_METADATA_DIR}/eventlog/\"\n$ }\n$ EOF\n$ cat /usr/local/etc/tpm2-tss/fapi-config.json\n```\n\nClear the TPM:\n```all\n$ tpm2_clear -c p\n```\n\nProvision a FAPI instance. The Storage Root Key (SRK) will be created based on the profile located at `profile_dir/profile_name` and made persistent at handle 0x81000001 (as specified in the profile) without an authorization value. TPM metadata will be stored in the directory `system_dir`:\n```all\n$ tss2_provision\n```\n\nSet the `TPM2_PKCS11_BACKEND` environment variable to `fapi` for using the FAPI backend:\n```all\n$ export TPM2_PKCS11_BACKEND=\"fapi\"\n```\n\n\u003c!--section-end--\u003e\n\n---\n\n# PKCS #11 Token Initialization\n\nInitialize a TPM2-based PKCS #11 token. The options include:\n1. **[pkcs11-tool from OpenSC](#pkcs11-tool-from-opensc)**\n2. **[tpm2_ptool from tpm2-pkcs11 (ESYSDB)](#tpm2_ptool-from-tpm2-pkcs11-esysdb)**\n3. **[p11tool from GnuTLS](#p11tool-from-gnutls)**\n\nLate import of TPM persistent keys or externally stored keys into the TPM2-based PKCS #11 token using vendor-specific PKCS #11 attributes:\n- **[key_import from tpm2-pkcs11](#key_import-from-tpm2-pkcs11)**\n\n## pkcs11-tool from OpenSC\n\u003c!--section:token-init-pkcs11-tool--\u003e\n\nInitialize a TPM2-based PKCS #11 token using `pkcs11-tool`.\n\u003e If the backend is ESYSDB and the backend store is not found, this process automatically creates the `tpm2_pkcs11.sqlite3` store,\n\u003e generates a SRK, and persistently stores it at the handle 0x81000001.\n\nCreate a token:\n```all\n$ pkcs11-tool-tpm2 --slot-index 0 --init-token --label tpm2-token --so-pin sopin\n$ pkcs11-tool-tpm2 --slot-index 0 --init-pin --so-pin sopin --login --pin userpin\n```\n\nList the token:\n```all\n$ pkcs11-tool-tpm2 --list-token-slots\n```\n\n\u003c!--section-end--\u003e\n\n## tpm2_ptool from tpm2-pkcs11 (ESYSDB)\n\nThis section only works with the ESYSDB backend. The tool directly modifies the ESYSDB backend store to make changes or additions. Subsequently, these changes will be reflected in the PKCS #11 interface.\n\nInitialize a TPM2-based PKCS #11 token using the Python-based `tpm2_ptool`. The options include automatically generating the SRK (Storage Root Key) as the default behavior or manually specifying the primary key:\n1. [Default Primary Key](#default-primary-key)\n2. [Custom Primary Key (Storage)](#custom-primary-key-storage)\n2. [Custom Primary Key (Platform)](#custom-primary-key-platform)\n\nFurthermore, `tpm2_ptool` enables the association of existing TPM externally stored keys (in Platform/Storage hierarchy) with the token:\n- [Link Existing Ordinary Keys (Storage)](#link-existing-ordinary-keys-storage)\n- [Link Existing Ordinary Keys (Platform)](#link-existing-ordinary-keys-platform)\n\nFor importing keys and certificates generated by third parties into the token using `tpm2_ptool`:\n- [Import 3rd Party Keys and Certificates](#import-3rd-party-keys-and-certificates)\n\n### Default Primary Key\n\u003c!--section:token-init-tpm2-ptool-default-primary-key--\u003e\n\nCreate the backend store `tpm2_pkcs11.sqlite3`, generate a SRK, and persistently store it at handle 0x81000001:\n\u003e If the hierarchy is protected by an authentication value, use the `--hierarchy-auth` option to set this value.\n\n\u003e It is possible to set the authentication value of the primary key using the option `--primary-auth`.\n```all\n$ pid=$(tpm2_ptool init --path $TPM2_PKCS11_STORE | grep id | sed 's/id: //')\n```\n\nCreate a token:\n```all\n$ tpm2_ptool addtoken --pid $pid --sopin sopin --userpin userpin \\\n    --label tpm2-token --path $TPM2_PKCS11_STORE\n```\n\nList the token:\n```all\n$ pkcs11-tool-tpm2 --list-token-slots\n```\n\n\u003c!--section-end--\u003e\n\n### Custom Primary Key (Storage)\n\u003c!--section:token-init-tpm2-ptool-custom-primary-key-storage--\u003e\n\nCreate the SRK:\n```all\n$ tpm2_createprimary -G ecc -c primary.ctx\n$ tpm2_evictcontrol -c primary.ctx 0x81000001\n```\n\nCreate the backend store `tpm2_pkcs11.sqlite3`, associating it with the specified primary handle:\n\u003e If the primary key is protected by an authentication value, use the `--primary-auth` option to set this value.\n```all\n$ export TPM2_PKCS11_STORE=$(mktemp -d)\n$ pid=$(tpm2_ptool init --primary-handle 0x81000001 --path $TPM2_PKCS11_STORE | grep id | sed 's/id: //')\n```\n\nCreate the token:\n```all\n$ tpm2_ptool addtoken --pid $pid --sopin sopin --userpin userpin \\\n    --label tpm2-token --path $TPM2_PKCS11_STORE\n```\n\nList the token:\n```all\n$ pkcs11-tool-tpm2 --list-token-slots\n```\n\n\u003c!--section-end--\u003e\n\n### Custom Primary Key (Platform)\n\u003c!--section:token-init-tpm2-ptool-custom-primary-key-platform--\u003e\n\nCreate the SRK:\n```all\n$ tpm2_createprimary -C p -G ecc -c primary.ctx\n$ tpm2_evictcontrol -C p -c primary.ctx 0x81800001\n```\n\nCreate the backend store `tpm2_pkcs11.sqlite3`, associating it with the specified primary handle:\n\u003e If the primary key is protected by an authentication value, use the `--primary-auth` option to set this value.\n```all\n$ export TPM2_PKCS11_STORE=$(mktemp -d)\n$ pid=$(tpm2_ptool init --primary-handle 0x81800001 --path $TPM2_PKCS11_STORE | grep id | sed 's/id: //')\n```\n\nCreate the token:\n```all\n$ tpm2_ptool addtoken --pid $pid --sopin sopin --userpin userpin \\\n    --label tpm2-token --path $TPM2_PKCS11_STORE\n```\n\nList the token:\n```all\n$ pkcs11-tool-tpm2 --list-token-slots\n```\n\n\u003c!--section-end--\u003e\n\n### Link Existing Ordinary Keys (Storage)\n\u003c!--section:token-init-tpm2-ptool-link-keys-storage--\u003e\n\nThis requires a token initialized with a primary key in the storage hierarchy.\n\nCreate the ordinary keys:\n```all\n$ tpm2_create -G rsa2048 -C 0x81000001 -u rsakey.pub -r rsakey.priv\n$ tpm2_create -G ecc -C 0x81000001 -u ecckey.pub -r ecckey.priv\n```\n\nLink existing RSA and ECC keys to the token:\n```all\n$ tpm2_ptool link --label tpm2-token --id 0 --key-label linked-rsa-2048 \\\n    --userpin userpin --path $TPM2_PKCS11_STORE rsakey.pub rsakey.priv\n$ tpm2_ptool link --label tpm2-token --id 1 --key-label linked-ecc-p256 \\\n    --userpin userpin --path $TPM2_PKCS11_STORE ecckey.pub ecckey.priv\n```\n\nRead the slot number:\n```all\n$ SLOT_INDEX=$(pkcs11-tool-tpm2 --list-token-slots | grep \"): tpm2-token\" | awk '{print $2}')\n```\n\nList the keys:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --list-objects --login --pin userpin\n```\n\n\u003c!--section-end--\u003e\n\n### Link Existing Ordinary Keys (Platform)\n\u003c!--section:token-init-tpm2-ptool-link-keys-platform--\u003e\n\nThis requires a token initialized with a primary key in the platform hierarchy.\n\nCreate the ordinary keys:\n```all\n$ tpm2_create -G rsa2048 -C 0x81800001 -u rsakey.pub -r rsakey.priv\n$ tpm2_create -G ecc -C 0x81800001 -u ecckey.pub -r ecckey.priv\n```\n\nLink existing RSA and ECC keys to the token:\n```all\n$ tpm2_ptool link --label tpm2-token --id 0 --key-label linked-rsa-2048 \\\n    --userpin userpin --path $TPM2_PKCS11_STORE rsakey.pub rsakey.priv\n$ tpm2_ptool link --label tpm2-token --id 1 --key-label linked-ecc-p256 \\\n    --userpin userpin --path $TPM2_PKCS11_STORE ecckey.pub ecckey.priv\n```\n\nRead the slot number:\n```all\n$ SLOT_INDEX=$(pkcs11-tool-tpm2 --list-token-slots | grep \"): tpm2-token\" | awk '{print $2}')\n```\n\nList the keys:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --list-objects --login --pin userpin\n```\n\n\u003c!--section-end--\u003e\n\n### Import 3rd Party Keys and Certificates\n\u003c!--section:token-init-tpm2-ptool-import-keys-certs--\u003e\n\nGenerate an RSA key and a self-signed CA certificate using OpenSSL:\n```all\n$ openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \\\n    -keyout ca.key.pem -out ca.crt.pem \\\n    -subj \"/C=DE/ST=Some-State/O=Some Inc./CN=dummy\"\n```\n\nImport the key to the token:\n```all\n$ tpm2_ptool import --label tpm2-token --key-label imported-ca-key \\\n    --userpin userpin --algorithm rsa --privkey ca.key.pem\n```\n\nAdd the certificate to the token:\n```all\n$ tpm2_ptool addcert --label tpm2-token --key-label imported-ca-key \\\n    --path $TPM2_PKCS11_STORE ca.crt.pem\n```\n\nRead the slot number:\n```all\n$ SLOT_INDEX=$(pkcs11-tool-tpm2 --list-token-slots | grep \"): tpm2-token\" | awk '{print $2}')\n```\n\nList the keys and certificates:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --list-objects --login --pin userpin\n```\n\n\u003c!--section-end--\u003e\n\n## p11tool from GnuTLS\n\u003c!--section:token-init-p11tool--\u003e\n\nInitialize a TPM-based PKCS #11 token using `p11tool`.\n\u003e If the backend is ESYSDB and the backend store is not found, this process automatically creates the `tpm2_pkcs11.sqlite3` store,\n\u003e generates a SRK, and persistently stores it at the handle 0x81000001.\n\nGet the token URL:\n```all\n$ TOKEN_URL=`p11tool --list-token-urls | head -n 1`\n```\n\nCreate a token:\n```all\n$ p11tool --initialize --label tpm2-token --set-so-pin sopin \"$TOKEN_URL\"\n```\n\nSet user pin:\n```all\n$ p11tool --initialize-pin --so-login --set-pin userpin \"pkcs11:token=tpm2-token;pin-value=sopin\"\n```\n\n\u003c!--section-end--\u003e\n\n## key_import from tpm2-pkcs11\n\u003c!--section:token-init-key-import--\u003e\n\nThe `key_import` tool from tpm2-pkcs11 is a C program that utilizes PKCS #11 vendor-specific attributes to import TPM2 keys (as persistent handles or externally stored key objects, with or without auth value). This approach does not directly modify the backend store. Instead, it uses the PKCS #11 standard interface along with vendor-specific attributes to import the keys. The advantage of this approach is the reduced dependency on additional tooling needed to perform the key import operation, and it works well with either backend (ESYSDB or FAPI). For more examples, please refer to [KEY_IMPORT_TOOL.md](https://github.com/tpm2-software/tpm2-pkcs11/blob/master/docs/KEY_IMPORT_TOOL.md).\n\nCreate the ordinary keys that will be imported later:\n```all\n# Externally stored key objects\n\n$ tpm2_create -G rsa2048 -C 0x81000001 -u rsakey.pub -r rsakey.priv\n$ tpm2_create -G ecc -C 0x81000001 -p ecckeyauth -u ecckey.pub -r ecckey.priv\n\n# Persistent keys\n\n$ tpm2_create -G rsa2048 -C 0x81000001 -p rsakeyauth -u rsakey_tmp.pub -r rsakey_tmp.priv\n$ tpm2_load -C 0x81000001 -u rsakey_tmp.pub -r rsakey_tmp.priv -c rsakey_tmp.ctx\n$ tpm2_evictcontrol -C o -c rsakey_tmp.ctx 0x81000011\n\n$ tpm2_create -G ecc -C 0x81000001 -u ecckey_tmp.pub -r ecckey_tmp.priv\n$ tpm2_load -C 0x81000001 -u ecckey_tmp.pub -r ecckey_tmp.priv -c ecckey_tmp.ctx\n$ tpm2_evictcontrol -C o -c ecckey_tmp.ctx 0x81000012\n```\n\nBefore proceeding, ensure that PKCS #11 token is initialized.\n\nRead the slot number using the `pkcs11_tool`. The slot numbers returned by the tool start from 0, while the slot numbers in the tpm2-pkcs11 library start from 1:\n```all\n$ SLOT_INDEX=$(pkcs11-tool-tpm2 --list-token-slots | grep \"): tpm2-token\" | awk '{print $2}')\n$ TPM2_PKCS11_SLOT_INDEX=$((SLOT_INDEX + 1))\n```\n\nImport the externally stored key objects:\n```all\n$ key_import --slot-id $TPM2_PKCS11_SLOT_INDEX --user-pin userpin \\\n    --tcti \"$TPM2TOOLS_TCTI\" \\\n    --parent-persistent-handle 0x81000001 \\\n    --public rsakey.pub \\\n    --private rsakey.priv \\\n    --key-label imported-rsa-2048-obj\n\n$ key_import --slot-id $TPM2_PKCS11_SLOT_INDEX --user-pin userpin \\\n    --tcti \"$TPM2TOOLS_TCTI\" \\\n    --parent-persistent-handle 0x81000001 \\\n    --public ecckey.pub \\\n    --private ecckey.priv \\\n    --key-auth ecckeyauth \\\n    --key-label imported-ecc-p256-obj\n```\n\nImport the persistent keys:\n```all\n$ key_import --slot-id $TPM2_PKCS11_SLOT_INDEX --user-pin userpin \\\n    --tcti \"$TPM2TOOLS_TCTI\" \\\n    --persistent-handle 0x81000011 \\\n    --key-auth rsakeyauth \\\n    --key-label imported-rsa-2048-persist\n\n$ key_import --slot-id $TPM2_PKCS11_SLOT_INDEX --user-pin userpin \\\n    --tcti \"$TPM2TOOLS_TCTI\" \\\n    --persistent-handle 0x81000012 \\\n    --key-label imported-ecc-p256-persist\n```\n\nList the keys:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --list-objects --login --pin userpin | tee log2verify\n$ cat log2verify | grep imported-rsa-2048-obj\n$ cat log2verify | grep imported-ecc-p256-obj\n$ cat log2verify | grep imported-rsa-2048-persist\n$ cat log2verify | grep imported-ecc-p256-persist\n$ rm log2verify\n```\n\nRead the public components:\n```all\n# key: imported-rsa-2048-obj\n\n$ rsa_obj_id=$(echo -n imported-rsa-2048-obj | xxd -p)\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin \\\n    --id $rsa_obj_id --type pubkey \\\n    --read-object --output-file rsa_obj.pub.der\n$ openssl rsa -inform DER -outform PEM -in rsa_obj.pub.der -pubin \\\n    -out rsa_obj.pub.pem\n$ cat rsa_obj.pub.pem\n\n# key: imported-ecc-p256-obj\n\n$ ecc_obj_id=$(echo -n imported-ecc-p256-obj | xxd -p)\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin \\\n    --id $ecc_obj_id --type pubkey \\\n    --read-object --output-file ecc_obj.pub.der\n$ openssl ec -inform DER -outform PEM -in ecc_obj.pub.der -pubin \\\n    -out ecc_obj.pub.pem\n$ cat ecc_obj.pub.pem\n\n# key: imported-rsa-2048-persist\n\n$ rsa_persist_id=$(echo -n imported-rsa-2048-persist | xxd -p)\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin \\\n    --id $rsa_persist_id --type pubkey \\\n    --read-object --output-file rsa_persist.pub.der\n$ openssl rsa -inform DER -outform PEM -in rsa_persist.pub.der -pubin \\\n    -out rsa_persist.pub.pem\n$ cat rsa_persist.pub.pem\n\n# key: imported-ecc-p256-persist\n\n$ ecc_persist_id=$(echo -n imported-ecc-p256-persist | xxd -p)\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin \\\n    --id $ecc_persist_id --type pubkey \\\n    --read-object --output-file ecc_persist.pub.der\n$ openssl ec -inform DER -outform PEM -in ecc_persist.pub.der -pubin \\\n    -out ecc_persist.pub.pem\n$ cat ecc_persist.pub.pem\n```\n\nCreate a file with random data:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --generate-random 32 \\\n    --output-file data.plain\n```\n\nPerform RSA encryption and decryption:\n```all\n# key: imported-rsa-2048-obj\n\n$ openssl rsautl -encrypt -inkey rsa_obj.pub.pem -in data.plain \\\n        -pubin -out data.cipher\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin \\\n    --id $rsa_obj_id --decrypt \\\n    --mechanism RSA-PKCS --input-file data.cipher \\\n    --output-file data.decipher\n$ diff data.plain data.decipher\n\n# key: imported-rsa-2048-persist\n\n$ openssl rsautl -encrypt -inkey rsa_persist.pub.pem -in data.plain \\\n        -pubin -out data.cipher\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin \\\n    --id $rsa_persist_id --decrypt \\\n    --mechanism RSA-PKCS --input-file data.cipher \\\n    --output-file data.decipher\n$ diff data.plain data.decipher\n```\n\nPerform RSA sign and verification:\n```all\n# key: imported-rsa-2048-obj\n\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --id $rsa_obj_id \\\n    --login --pin userpin --sign \\\n    --mechanism SHA256-RSA-PKCS --input-file data.plain \\\n    --output-file data.rsa.sig\n$ openssl dgst -sha256 -verify rsa_obj.pub.pem \\\n    -signature data.rsa.sig data.plain\n\n# key: imported-rsa-2048-persist\n\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --id $rsa_persist_id \\\n    --login --pin userpin --sign \\\n    --mechanism SHA256-RSA-PKCS --input-file data.plain \\\n    --output-file data.rsa.sig\n$ openssl dgst -sha256 -verify rsa_persist.pub.pem \\\n    -signature data.rsa.sig data.plain\n```\n\nPerform ECC sign and verification:\n```all\n# key: imported-ecc-p256-obj\n\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --id $ecc_obj_id \\\n    --login --pin userpin --sign \\\n    --mechanism ECDSA-SHA1 --signature-format openssl \\\n    --input-file data.plain --output-file data.ec.sig\n$ openssl dgst -sha1 -verify ecc_obj.pub.pem \\\n    -signature data.ec.sig data.plain\n\n# key: imported-ecc-p256-persist\n\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --id $ecc_persist_id \\\n    --login --pin userpin --sign \\\n    --mechanism ECDSA-SHA1 --signature-format openssl \\\n    --input-file data.plain --output-file data.ec.sig\n$ openssl dgst -sha1 -verify ecc_persist.pub.pem \\\n    -signature data.ec.sig data.plain\n```\n\n\u003c!--section-end--\u003e\n\n---\n\n# Tools for Accessing PKCS #11 Tokens\n\nTools available for operations on a PKCS #11 token include:\n- [pkcs11-tool from OpenSC](#pkcs11-tool-from-opensc-1)\n- [libp11 from OpenSC (OpenSSL)](#libp11-from-opensc-openssl)\n- [p11-kit](#p11-kit)\n- [p11tool from GnuTLS](#p11tool-from-gnutls-1)\n- [NSS Tools](#nss-tools)\n\n## pkcs11-tool from OpenSC\n\u003c!--section:tools-pkcs11-tool--\u003e\n\nThe pkcs11-tool is one of the command-line tools provided by [OpenSC](https://github.com/OpenSC/OpenSC). This section introduces the tool through a series of practical examples, demonstrating its capabilities and usage.\n\nThe pkcs11-tool is installed during the setup stage through the installation of the `opensc` package.\n\nCheck the version of the `opensc` package and its dependencies:\n```all\n$ apt show opensc\n$ apt-cache depends opensc | grep Depends: | cut -d \":\" -f2 | xargs dpkg -l\n```\n\nList available tokens:\n```all\n$ pkcs11-tool-tpm2 --list-token-slots\n```\n\nRead the slot number:\n```all\n$ SLOT_INDEX=$(pkcs11-tool-tpm2 --list-token-slots | grep \"): tpm2-token\" | awk '{print $2}')\n```\n\nGenerate random bytes:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --generate-random 32 --output-file data.plain\n```\n\nChange the SO pin:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --change-pin --login --login-type so --so-pin sopin --new-pin sopin2\n```\n\nRestore the SO pin:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --change-pin --login --login-type so --so-pin sopin2 --new-pin sopin\n```\n\nChange the user pin using user credential (from \"userpin\" to \"upin\"):\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --change-pin --login --pin userpin --new-pin upin\n```\n\nChange the user pin using SO credential (from \"upin\" to \"userpin\"):\n```all\n# This is required for the FAPI backend; otherwise, the overwrite check will fail.\n$ rm -rf ${FAPI_METADATA_DIR}/user/keystore/P_RSA2048SHA256/HS/SRK/tpm2-pkcs11-token-usr-00000001\n\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --init-pin --login --login-type so --so-pin sopin --new-pin userpin\n```\n\nDisplay supported mechanisms:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --list-mechanisms\n```\n\nCreate an RSA key:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --id 00 --label rsa2048 --login --pin userpin \\\n    --keypairgen --key-type RSA:2048\n```\n\nCreate an ECC key:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --id 01 --label eccp256 --login --pin userpin \\\n    --keypairgen --usage-sign --key-type EC:secp256r1\n```\n\nList the created keys:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --list-objects --login --pin userpin\n```\n\nRead the public component of the RSA key:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin --id 00 --type pubkey \\\n    --read-object --output-file rsa.pub.der\n$ openssl rsa -inform DER -outform PEM -in rsa.pub.der -pubin -out rsa.pub.pem\n```\n\nRead the public component of the ECC key:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin --id 01 --type pubkey \\\n    --read-object --output-file ecc.pub.der\n$ openssl ec -inform DER -outform PEM -in ecc.pub.der -pubin -out ecc.pub.pem\n```\n\nPerform RSA encryption and decryption:\n```all\n$ openssl rsautl -encrypt -inkey rsa.pub.pem -in data.plain -pubin -out data.cipher\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin --id 00 --decrypt \\\n    --mechanism RSA-PKCS --input-file data.cipher \\\n    --output-file data.decipher\n$ diff data.plain data.decipher\n```\n\nPerform RSA signing and signature verification:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --id 00 --login --pin userpin --sign \\\n    --mechanism SHA256-RSA-PKCS --input-file data.plain \\\n    --output-file data.rsa.sig\n$ openssl dgst -sha256 -verify rsa.pub.pem -signature data.rsa.sig data.plain\n```\n\nPerform ECC signing and signature verification:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --id 01 --login --pin userpin --sign \\\n    --mechanism ECDSA-SHA1 --signature-format openssl \\\n    --input-file data.plain --output-file data.ecc.sig\n$ openssl dgst -sha1 -verify ecc.pub.pem -signature data.ecc.sig data.plain\n```\n\nDestroy the RSA key:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin --delete-object --type privkey --id 00\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin --delete-object --type pubkey --id 00\n```\n\nDestroy the ECC key:\n```all\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin --delete-object --type privkey --id 01\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --login --pin userpin --delete-object --type pubkey --id 01\n```\n\n\u003c!--section-end--\u003e\n\n## libp11 from OpenSC (OpenSSL)\n\n[libp11](https://github.com/OpenSC/libp11) is a PKCS #11 engine plugin for the OpenSSL library, provided by [OpenSC](https://github.com/OpenSC). Since the OpenSSL engine was deprecated with the release of OpenSSL 3, and OpenSSL now recommends using Providers instead of Engines, examples of using libp11 will not be covered here. Currently, OpenSC does not officially support a PKCS #11 provider, as discussed in this [issue](https://github.com/OpenSC/libp11/issues/432).\n\n## p11-kit\n\u003c!--section:tools-p11-kit--\u003e\n\nThe [p11-kit](https://github.com/p11-glue/p11-kit) project includes the libp11-kit library for loading, enumerating, and [managing](https://p11-glue.github.io/p11-glue/p11-kit/manual/sharing-managed.html) PKCS #11 modules and also comes bundled with a command-line tool. This section introduces the tool through a series of practical examples, showcasing its capabilities and usage.\n\nThe p11-kit project is built and installed during the setup stage.\n\nPlease refer to the p11-kit installation section to learn how p11-kit discovers PKCS #11 modules (e.g., `libtpm2_pkcs11.so` from tpm2-pkcs11).\n\nList available tokens:\n```all\n$ p11-kit list-modules\n```\n\nDisplay a token information:\n```all\n$ p11-kit list-tokens \"pkcs11:token=tpm2-token\"\n```\n\nDisplay supported mechanisms:\n```all\n$ p11-kit list-mechanisms \"pkcs11:token=tpm2-token\"\n```\n\nCreate an RSA key:\n```all\n$ p11-kit generate-keypair --label rsa2048 --type rsa --bits 2048 --login \"pkcs11:token=tpm2-token;pin-value=userpin\"\n```\n\nCreate an ECC key:\n```all\n$ p11-kit generate-keypair --label eccp256 --type ecdsa --curve secp256r1 --login \"pkcs11:token=tpm2-token;pin-value=userpin\"\n```\n\nList the created keys:\n```all\n$ p11-kit list-objects --login \"pkcs11:object=rsa2048;pin-value=userpin\"\n$ p11-kit list-objects --login \"pkcs11:object=eccp256;pin-value=userpin\"\n```\n\nRead the public component of the RSA key:\n```all\n$ p11-kit export-object --login \"pkcs11:token=tpm2-token;object=rsa2048;type=public;pin-value=userpin\" \u003e rsa.pub.pem\n```\n\nRead the public component of the ECC key:\n```all\n$ p11-kit export-object --login \"pkcs11:token=tpm2-token;object=eccp256;type=public;pin-value=userpin\" \u003e ecc.pub.pem\n```\n\nImport a dummy certificate:\n```all\n$ openssl req -x509 -newkey rsa:2048 -keyout ca.key.pem -out ca.cert.pem -sha256 -days 365 -nodes -subj \"/CN=dummy\"\n$ p11-kit import-object --file ca.cert.pem --label dummy-cert --login \"pkcs11:token=tpm2-token;pin-value=userpin\"\n$ p11-kit list-objects \"pkcs11:object=dummy-cert\"\n```\n\nExport the dummy certificate:\n```all\n$ p11-kit export-object --login \"pkcs11:token=tpm2-token;object=dummy-cert;pin-value=userpin\" \u003e ca.key.pem\n```\n\nDestroy the keys and certificate:\n```all\n$ p11-kit delete-object --login \"pkcs11:object=rsa2048;type=public;pin-value=userpin\"\n$ p11-kit delete-object --login \"pkcs11:object=rsa2048;type=private;pin-value=userpin\"\n$ p11-kit delete-object --login \"pkcs11:object=eccp256;type=public;pin-value=userpin\"\n$ p11-kit delete-object --login \"pkcs11:object=eccp256;type=private;pin-value=userpin\"\n$ p11-kit delete-object --login \"pkcs11:object=dummy-cert;pin-value=userpin\"\n```\n\n\u003c!--section-end--\u003e\n\n## p11tool from GnuTLS\n\u003c!--section:tools-p11tool--\u003e\n\nThe p11tool from GnuTLS is a command-line tool designed to interact with PKCS#11 tokens, utilizing the libp11-kit library from the [p11-kit](https://github.com/p11-glue/p11-kit) project.\n\nThe p11tool is installed during the setup stage through the gnutls-bin package, but it is overwritten by installing the GnuTLS project from source.\n\nTo set the pin, you may use the environment variable `GNUTLS_PIN`/`GNUTLS_SO_PIN` or include `pin-value=` in the URL.\n\nSet the pin:\n```all\n$ export GNUTLS_PIN=\"userpin\"\n$ export GNUTLS_SO_PIN=\"sopin\"\n```\n\nCheck the p11tool version:\n```all\n$ p11tool --version\n```\n\nList available tokens:\n```all\n$ p11tool --list-tokens\n```\n\nChange then restore the SO pin:\n```all\n$ GNUTLS_SO_PIN=sopin GNUTLS_NEW_SO_PIN=sopin2 p11tool --initialize-so-pin \"pkcs11:token=tpm2-token\"\n$ GNUTLS_SO_PIN=sopin2 GNUTLS_NEW_SO_PIN=sopin p11tool --initialize-so-pin \"pkcs11:token=tpm2-token\"\n```\n\nChange the user pin using SO credentials (for demonstration purposes, change to the same pin).\n```all\n# This is required for the FAPI backend; otherwise, the overwrite check will fail.\n$ rm -rf ${FAPI_METADATA_DIR}/user/keystore/P_RSA2048SHA256/HS/SRK/tpm2-pkcs11-token-usr-00000001\n\n$ p11tool --initialize-pin --so-login --set-pin userpin \"pkcs11:token=tpm2-token;pin-value=sopin\"\n```\n\nDisplay supported mechanisms:\n```all\n$ p11tool --list-mechanisms \"pkcs11:token=tpm2-token\"\n```\n\nCreate an RSA key and output its public component:\n```all\n$ p11tool --generate-privkey rsa --bits 2048 --label rsa2048 --outfile rsa.pub.pem --login \"pkcs11:token=tpm2-token?pin-value=userpin\"\n```\n\nCreate an ECC key and output its public component:\n```all\n$ p11tool --generate-privkey ecdsa --curve secp256r1 --label eccp256 --outfile ecc.pub.pem --login \"pkcs11:token=tpm2-token?pin-value=userpin\"\n```\n\nList all available objects:\n```all\n$ p11tool --list-all --login \"pkcs11:token=tpm2-token?pin-value=userpin\"\n```\n\nImport a dummy certificate:\n```all\n$ openssl req -x509 -newkey rsa:2048 -keyout ca.key.pem -out ca.cert.pem -sha256 -days 365 -nodes -subj \"/CN=dummy\"\n$ p11tool --write --load-certificate ca.cert.pem --label dummy-cert --login \"pkcs11:token=tpm2-token?pin-value=userpin\"\n$ p11tool --list-all-cert \"pkcs11:token=tpm2-token\"\n```\n\nExport the dummy certificate:\n```all\n$ p11tool --export-chain \"pkcs11:token=tpm2-token;object=dummy-cert\" --outfile ca.cert.pem\n```\n\nDestroy the keys and certificate:\n```all\n$ p11tool --delete --batch --login \"pkcs11:token=tpm2-token;object=rsa2048?pin-value=userpin\"\n$ p11tool --delete --batch --login \"pkcs11:token=tpm2-token;object=eccp256?pin-value=userpin\"\n$ p11tool --delete --batch --login \"pkcs11:token=tpm2-token;object=dummy-cert?pin-value=userpin\"\n```\n\n\u003c!--section-end--\u003e\n\n## NSS Tools\n\u003c!--section:tools-nss-tools--\u003e\n\nOriginally known as [Netscape Security Services, Network Security Services (NSS)](https://firefox-source-docs.mozilla.org/security/nss/index.html) is a suite of libraries designed to support the cross-platform development of security-enabled client and server applications. The NSS-tools includes tools for developing, debugging, and managing applications that utilize these libraries.\n\nNSS command-line tools are installed during the setup stage via the `libnss3-tools` package.\n\nCheck the version of the `libnss3-tools` package and its dependencies:\n```all\n$ apt show libnss3-tools\n$ apt-cache depends libnss3-tools | grep Depends: | cut -d \":\" -f2 | xargs dpkg -l\n```\n\nSet the location of the NSS database path:\n```all\n$ export NSSDB_DIR=$(mktemp -d)\n```\n\nCreate an empty NSS database:\n\u003e This process creates three files: `cert9.db`, `key4.db`, and `pkcs11.txt`. If no external token is specified, the internal slot will be used. An internal slot is a virtual slot maintained within the NSS software (NSS Internal PKCS #11 Module), and its associated certificate and key database are stored in `cert9.db` and `key4.db`, respectively. The list of loaded PKCS #11 modules is stored in `pkcs11.txt`.\n```all\n$ certutil -N -d \"sql:$NSSDB_DIR\" --empty-password\n$ ls -la $NSSDB_DIR\n```\n\nGenerate a noise file for seeding purposes:\n```all\n$ SLOT_INDEX=$(pkcs11-tool-tpm2 --list-token-slots | grep \"): tpm2-token\" | awk '{print $2}')\n$ pkcs11-tool-tpm2 --slot-index $SLOT_INDEX --generate-random 32 --output-file noise.bin\n\n# or\n\n$ dd if=/dev/random of=noise.bin bs=32 count=1\n```\n\n\u003cb\u003e\u003cins\u003eOperations on NSS Internal PKCS #11 Module:\u003c/ins\u003e\u003c/b\u003e\n\nDisplay the list of modules and their associated slots:\n```all\n$ modutil -list -dbdir \"sql:$NSSDB_DIR\" | grep \"NSS Internal PKCS #11 Module\"\n```\n\nDisplay the details of the module:\n```all\n$ modutil -list \"NSS Internal PKCS #11 Module\" -dbdir \"sql:$NSSDB_DIR\"\n```\n\nCreate a self-signed CA certificate and its associated CA key:\n\u003e Make it non-interactive by adding `echo -ne \"y\\ny\"` to respond to the following prompts:\n\u003e - Is this a CA certificate [y/N]?\n\u003e - Enter the path length constraint, press enter to skip [\u003c0 for unlimited path]:\n\u003e - Is this a critical extension [y/N]?\n```all\n$ echo -ne \"y\\ny\" | certutil -S -s \"CN=Software CA\" \\\n    -n \"software-ca\" -x -t \"C,C,C\" -2 \\\n    -7 software-ca@example.com \\\n    --keyUsage certSigning,crlSigning,critical \\\n    --nsCertType objectSigningCA,critical \\\n    -d \"sql:$NSSDB_DIR\" -z noise.bin\n```\n\nList the CA key:\n```all\n$ certutil -K -d \"sql:$NSSDB_DIR\" | grep \"NSS Certificate DB:software-ca\"\n```\n\nList the CA certificate:\n```all\n$ certutil -L -d \"sql:$NSSDB_DIR\" | grep \"software-ca\"\n```\n\nPrint the information of the CA certificate:\n```all\n# Output in PEM encoding\n$ certutil -L -d \"sql:$NSSDB_DIR\" -a -n \"software-ca\" \u003e ca.crt.pem\n$ openssl x509 -in ca.crt.pem -text -noout\n\n# Output in human-readable format directly\n$ certutil -L -d \"sql:$NSSDB_DIR\" -n \"software-ca\"\n```\n\nCreate a client key and its associated Certificate Signing Request (CSR):\n```all\n$ certutil -R -k rsa -g 2048 -s \"CN=Example,O=Example Corp,C=DE\" \\\n    -7 software-client@example.com \\\n    -d \"sql:$NSSDB_DIR\" -z noise.bin -a -o client.csr.pem\n```\n\nPrint the information of the client CSR:\n```all\n$ openssl req -in client.csr.pem -text -noout\n```\n\nList the client key:\n\u003e The key will remain in an \"orphan\" state until the associated certificate is added.\n```all\n$ certutil -K -d \"sql:$NSSDB_DIR\" | grep \"orphan\"\n```\n\nConvert the CSR from PEM encoding to DER encoding:\n```all\n$ openssl req -in client.csr.pem -outform DER -out client.csr.der\n```\n\nUse the software CA to issue a certificate from the CSR:\n```all\n# When the \"-m\" option is not specified in certutil, the serial number\n# is generated based on the current time. Therefore, to ensure the\n# uniqueness of the serial number, introduce a delay of 1 second.\n$ sleep 1\n\n$ certutil -C -c \"software-ca\" -i client.csr.der -o client.crt.der \\\n    -v 12 -w -1 -d \"sql:$NSSDB_DIR\" \\\n    --keyUsage digitalSignature,keyEncipherment,critical \\\n    -7 software-client@example.com\n```\n\nAdd the client certificate to the NSS Certificate DB:\n```all\n$ certutil -A -n \"software-client\" -t \",,\" -d \"sql:$NSSDB_DIR\" -i client.crt.der\n```\n\nPrint the information of the client certificate:\n```all\n# Output in PEM encoding\n$ certutil -L -d \"sql:$NSSDB_DIR\" -a -n \"software-client\" \u003e client.crt.pem\n$ openssl x509 -in client.crt.pem -text -noout\n\n# Output in human-readable format directly\n$ certutil -L -d \"sql:$NSSDB_DIR\" -n \"software-client\"\n```\n\nList the client certificate chain:\n```all\n$ certutil -O -d \"sql:$NSSDB_DIR\" -n \"software-client\"\n```\n\nList the client certificate:\n```all\n$ certutil -L -d \"sql:$NSSDB_DIR\" | grep \"software-client\"\n```\n\nList the client key:\n\u003e The key will no longer be in an \"orphan\" state.\n```all\n$ certutil -K -d \"sql:$NSSDB_DIR\" | grep \"NSS Certificate DB:software-client\"\n```\n\nCreate a message:\n```all\n$ echo \"Hello world!\" \u003e message.plain\n```\n\nPerform digital signing and verification using the client key:\n```all\n# Sign\n$ cmsutil -S -d \"sql:$NSSDB_DIR\" -N \"software-client\" -i message.plain -o message.sig.cms\n\n# Verify\n$ cmsutil -D -d \"sql:$NSSDB_DIR\" -i message.sig.cms\n```\n\nPerform digital signing and verification using the client key:\n\u003e Use the `-T` option to suppress content in the CMS message. This means the message will be detached from the signature file.\n\u003e During signature verification, the message must be explicitly provided through the `-c` detached content option.\n```all\n# Sign\n$ cmsutil -S -d \"sql:$NSSDB_DIR\" -N \"software-client\" -T -i message.plain -o message.sig.cms\n\n# Verify\n$ cmsutil -D -d \"sql:$NSSDB_DIR\" -i message.sig.cms -c message.plain\n```\n\nPerform message encryption and decryption using the client key:\n```all\n# Encrypt\n$ cmsutil -E -d \"sql:$NSSDB_DIR\" -r \"software-client\" -i message.plain -o message.cipher.cms\n\n# Decrypt\n$ cmsutil -D -d \"sql:$NSSDB_DIR\" -i message.cipher.cms -o message.decipher.cms\n$ diff message.plain message.decipher.cms\n```\n\nDelete the client key and its associated certificate:\n\u003e Optionally, delete only the client certificate while retaining the key by: `certutil -D -d \"sql:$NSSDB_DIR\" -n \"software-client\"`\n```all\n$ certutil -F -d \"sql:$NSSDB_DIR\" -n \"software-client\"\n```\n\n\u003cb\u003e\u003cins\u003eOperations on TPM2-based PKCS #11 Module:\u003c/ins\u003e\u003c/b\u003e\n\nAdd the TPM2-based PKCS #11 module to the NSS database:\n```all\n$ echo -ne \"\\n\" | modutil -add \"TPM2-based PKCS #11 Module\" \\\n    -libfile \"${HOME}/tpm2-pkcs11/src/.libs/libtpm2_pkcs11.so\" \\\n    -dbdir \"sql:$NSSDB_DIR\"\n```\n\nDisplay the list of modules and their associated slots:\n```all\n$ modutil -list -dbdir \"sql:$NSSDB_DIR\" | grep \"TPM2-based PKCS #11 Module\"\n$ modutil -list -dbdir \"sql:$NSSDB_DIR\" | grep \"tpm2-token\"\n```\n\nDisplay the details of the module:\n```all\n$ modutil -list \"TPM2-based PKCS #11 Module\" -dbdir \"sql:$NSSDB_DIR\"\n```\n\nDisable and then re-enable the module:\n```all\n$ echo -ne \"\\n\" | modutil -disable \"TPM2-based PKCS #11 Module\" -slot \"tpm2-token\" -dbdir \"sql:$NSSDB_DIR\"\n$ echo -ne \"\\n\" | modutil -enable \"TPM2-based PKCS #11 Module\" -slot \"tpm2-token\" -dbdir \"sql:$NSSDB_DIR\"\n```\n\nSave the user PIN to a file for non-interactive setup:\n\u003e This is for demonstration purposes only. It is not secure to save the user PIN in a file that can be accessed by anyone.\n```all\n$ echo \"userpin\" \u003e userpin.txt\n```\n\nCreate a self-signed CA certificate and its associated CA key:\n\u003e Make it non-interactive by adding `echo -ne \"y\\ny\"` to respond to the following prompts:\n\u003e - Is this a CA certificate [y/N]?\n\u003e - Enter the path length constraint, press enter to skip [\u003c0 for unlimited path]:\n\u003e - Is this a critical extension [y/N]?\n\n\u003e Although the operation is successful, it will report an error in the background because the current version of tpm2-pkcs11 does not support the vendor-defined object class `CKO_NSS_TRUST`. This error occurs during the creation of object class `CKO_NSS_TRUST` through `C_CreateObject`. This error may not be fatal here but may have side effects on subsequent operations. Use at your own risk.\n```all\n$ echo -ne \"y\\ny\" | certutil -S -h \"tpm2-token\" -f \"userpin.txt\" \\\n    -s \"CN=TPM2 CA\" -7 tpm2-ca@example.com \\\n    -n \"tpm2-ca\" -x -t \"C,C,C\" -2 \\\n    --keyUsage certSigning,crlSigning,critical \\\n    --nsCertType objectSigningCA,critical \\\n    -d \"sql:$NSSDB_DIR\" -z noise.bin\n```\n\nCreate a TPM2 key and its associated Certificate Signing Request (CSR):\n```all\n$ certutil -R -k rsa -g 2048 -s \"CN=Example2,O=Example2 Corp,C=DE\" \\\n    -d \"sql:$NSSDB_DIR\" -h \"tpm2-token\" -f \"userpin.txt\" \\\n    -7 tpm2-client@example.com \\\n    -z noise.bin -a -o tpm2-client.csr.pem\n```\n\nPrint the information of the client CSR:\n```all\n$ openssl req -in tpm2-client.csr.pem -text -noout\n```\n\nList the TPM2 key:\n\u003e The key will remain in an \"orphan\" state until the associated certificate is added.\n```all\n$ certutil -K -d \"sql:$NSSDB_DIR\" -h \"tpm2-token\" -f \"userpin.txt\" | grep \"orphan\"\n```\n\nConvert the CSR from PEM encoding to DER encoding:\n```all\n$ openssl req -in tpm2-client.csr.pem -outform DER -out tpm2-client.csr.der\n```\n\nUse the TPM2 CA to issue a certificate from the CSR:\n```all\n# When the \"-m\" option is not specified in certutil, the serial number\n# is generated based on the current time. Therefore, to ensure the\n# uniqueness of the serial number, introduce a delay of 1 second.\n$ sleep 1\n\n$ ~/pkcs11-optiga-tpm/scripts/cmdAutoFillPw.sh userpin \\\n    certutil -C -c \"tpm2-token:tpm2-ca\" \\\n    -i tpm2-client.csr.der -o tpm2-client.crt.der \\\n    -v 12 -w -1 -d \"sql:$NSSDB_DIR\" \\\n    --keyUsage digitalSignature,keyEncipherment,critical \\\n    -7 tpm2-client@example.com\n```\n\nAdd the client certificate:\n\u003e The same non-fatal error related to `CKO_NSS_TRUST` will be seen here.\n\n\u003e Trust flag \"u\" is set automatically if the private key is present in the token.\n```all\n$ certutil -A -n \"tpm2-client\" -t \",,\" -d \"sql:$NSSDB_DIR\" \\\n    -i tpm2-client.crt.der -h \"tpm2-token\" -f \"userpin.txt\"\n```\n\nPrint the information of the client certificate:\n```all\n# Output in PEM encoding\n$ certutil -L -d \"sql:$NSSDB_DIR\" -a -n \"tpm2-client\" \u003e tpm2-client.crt.pem\n$ openssl x509 -in tpm2-client.crt.pem -text -noout\n\n# Output in human-readable format directly\n$ certutil -L -d \"sql:$NSSDB_DIR\" -n \"tpm2-client\"\n```\n\nList the client certificate chain:\n```all\n$ ~/pkcs11-optiga-tpm/scripts/cmdAutoFillPw.sh userpin certutil -O \\\n    -d \"sql:$NSSDB_DIR\" -h \"pkcs11:token=tpm2-token\" -n \"tpm2-token:tpm2-client\"\n```\n\nList the client certificate:\n```all\n$ certutil -L -d \"sql:$NSSDB_DIR\" -h \"pkcs11:token=tpm2-token\" -f \"userpin.txt\" \\\n    | grep \"tpm2-token:tpm2-client\"\n```\n\nList the TPM2 key:\n\u003e The key will no longer be in an \"orphan\" state.\n```all\n$ certutil -K -d \"sql:$NSSDB_DIR\" -h \"pkcs11:token=tpm2-token\" -f \"userpin.txt\" \\\n    | grep \"tpm2-token:tpm2-client\"\n```\n\nCreate a message:\n```all\n$ echo \"Hello world!\" \u003e message.txt\n```\n\nPerform digital signing and verification using the client key:\n```all\n# Sign\n$ cmsutil -S -d \"sql:$NSSDB_DIR\" -N \"tpm2-token:tpm2-client\" \\\n    -f \"userpin.txt\" -i message.plain -o message.sig.cms\n\n# Verify\n$ cmsutil -D -d \"sql:$NSSDB_DIR\" -i message.sig.cms\n```\n\nPerform digital signing and verification using the client key:\n\u003e Use the `-T` option to suppress content in the CMS message. This means the message will be detached from the signature file.\n\u003e During signature verification, the message must be explicitly provided through the `-c` detached content option.\n```all\n# Sign\n$ cmsutil -S -d \"sql:$NSSDB_DIR\" -N \"tpm2-token:tpm2-client\" \\\n    -f \"userpin.txt\" -T -i message.plain -o message.sig.cms\n\n# Verify\n$ cmsutil -D -d \"sql:$NSSDB_DIR\" -i message.sig.cms -c message.plain\n```\n\nPerform message encryption and decryption using the client key:\n\u003e Message decryption is not functioning because tpm2-pkcs11 does not support `C_UnwrapKey` and session objects, and its implementation of `C_CreateObject` does not support creating objects of the class `CKO_SECRET_KEY`, which are necessary to store the message decryption AES key during the decryption process.\n```all\n# Encrypt\n$ ~/pkcs11-optiga-tpm/scripts/cmdAutoFillPw.sh userpin cmsutil -E -d \"sql:$NSSDB_DIR\" \\\n    -r \"tpm2-token:tpm2-client\" -i message.plain -o message.cipher.cms\n\n# Decrypt\n# Skipped\n```\n\nDelete the client key and its associated certificate:\n\u003e Optionally, delete only the client certificate while retaining the key by: `certutil -D -d \"sql:$NSSDB_DIR\" -h \"tpm2-token\" -f \"userpin.txt\" -n \"tpm2-token:tpm2-client\"`\n```all\n$ certutil -F -d \"sql:$NSSDB_DIR\" -h \"tpm2-token\" -f \"userpin.txt\" -n \"tpm2-token:tpm2-client\"\n```\n\nHousekeeping:\n```all\n$ rm -rf $NSSDB_DIR\n$ unset NSSDB_DIR\n```\n\n\u003c!--section-end--\u003e\n\n---\n\n# Housekeeping\n\n## Housekeeping (ESYSDB)\n\u003c!--section:housekeeping-esysdb--\u003e\n\nClear the TPM:\n```all\n$ tpm2_clear -c p\n```\n\nRemove the ESYSDB database:\n```all\n$ rm -rf $TPM2_PKCS11_STORE\n$ unset TPM2_PKCS11_STORE\n```\n\nThis is only necessary if the platform hierarchy is utilized:\n```all\n$ tpm2_evictcontrol -C p -c 0x81800001 || true\n```\n\n\u003c!--section-end--\u003e\n\n## Housekeeping (FAPI)\n\u003c!--section:housekeeping-fapi--\u003e\n\nClear the TPM:\n```all\n$ tpm2_clear -c p\n```\n\nRemove the FAPI metadata:\n```all\n$ rm -rf $FAPI_METADATA_DIR\n$ unset FAPI_METADATA_DIR\n```\n\n\u003c!--section-end--\u003e\n\n---\n\n# GitHub Actions\n\nThis section is intended for maintainers only.\n\nGitHub Actions has been set up to automate the testing of this integration guide as part of the CI/CD process. The testing methodology involves extracting command lines from the markdown and running them in a Docker container. Please refer to [script.sh](.github/docker/script.sh) to see the preparation of commands for testing. The process occurs seamlessly in the background, utilizing hidden tags in the README.md (visible in raw mode).\n\nCommands are divided into sections using the markers `\u003c!--section:xxx--\u003e` and `\u003c!--section-end--\u003e`. This structure allows for the execution of specific sections multiple times (e.g., housekeeping) and allows for the flexibility of reordering or creating new test sequences. The test sequence construction (e.g., section 1 -\u003e section 2 -\u003e section 3 -\u003e ...) is configurable.\n\nTo learn about the CI test sequence, refer to the README.md in raw mode and specifically look for `\u003c!--tests:`.\n\nFor debugging, it is possible to download the executed test scripts from the Artifacts of a GitHub Actions run.\n\n---\n\n# License\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n\u003c!--tests:\nsetup-pt1;setup-esysdb-install;setup-pt2;\n\nbackend-init-esysdb;token-init-pkcs11-tool;tools-pkcs11-tool;housekeeping-esysdb;\nbackend-init-esysdb;token-init-pkcs11-tool;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-pkcs11-tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-default-primary-key;tools-pkcs11-tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-default-primary-key;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-pkcs11-tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-storage;tools-pkcs11-tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-storage;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-pkcs11-tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-platform;tools-pkcs11-tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-platform;token-init-tpm2-ptool-link-keys-platform;token-init-tpm2-ptool-import-keys-certs;tools-pkcs11-tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-p11tool;tools-pkcs11-tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-p11tool;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-pkcs11-tool;housekeeping-esysdb\n\nbackend-init-esysdb;token-init-pkcs11-tool;tools-p11-kit;housekeeping-esysdb;\nbackend-init-esysdb;token-init-pkcs11-tool;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-p11-kit;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-default-primary-key;tools-p11-kit;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-default-primary-key;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-p11-kit;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-storage;tools-p11-kit;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-storage;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-p11-kit;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-platform;tools-p11-kit;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-platform;token-init-tpm2-ptool-link-keys-platform;token-init-tpm2-ptool-import-keys-certs;tools-p11-kit;housekeeping-esysdb\nbackend-init-esysdb;token-init-p11tool;tools-p11-kit;housekeeping-esysdb\nbackend-init-esysdb;token-init-p11tool;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-p11-kit;housekeeping-esysdb\n\nbackend-init-esysdb;token-init-pkcs11-tool;tools-p11tool;housekeeping-esysdb;\nbackend-init-esysdb;token-init-pkcs11-tool;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-p11tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-default-primary-key;tools-p11tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-default-primary-key;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-p11tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-storage;tools-p11tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-storage;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-p11tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-platform;tools-p11tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-platform;token-init-tpm2-ptool-link-keys-platform;token-init-tpm2-ptool-import-keys-certs;tools-p11tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-p11tool;tools-p11tool;housekeeping-esysdb\nbackend-init-esysdb;token-init-p11tool;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-p11tool;housekeeping-esysdb\n\nbackend-init-esysdb;token-init-pkcs11-tool;tools-nss-tools;housekeeping-esysdb;\nbackend-init-esysdb;token-init-pkcs11-tool;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-nss-tools;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-default-primary-key;tools-nss-tools;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-default-primary-key;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-nss-tools;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-storage;tools-nss-tools;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-storage;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-nss-tools;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-platform;tools-nss-tools;housekeeping-esysdb\nbackend-init-esysdb;token-init-tpm2-ptool-custom-primary-key-platform;token-init-tpm2-ptool-link-keys-platform;token-init-tpm2-ptool-import-keys-certs;tools-nss-tools;housekeeping-esysdb\nbackend-init-esysdb;token-init-p11tool;tools-nss-tools;housekeeping-esysdb\nbackend-init-esysdb;token-init-p11tool;token-init-tpm2-ptool-link-keys-storage;token-init-tpm2-ptool-import-keys-certs;token-init-key-import;tools-nss-tools;housekeeping-esysdb\n\nsetup-fapi-install;\n\nbackend-init-fapi;token-init-pkcs11-tool;token-init-key-import;tools-pkcs11-tool;housekeeping-fapi;\nbackend-init-fapi;token-init-p11tool;token-init-key-import;tools-pkcs11-tool;housekeeping-fapi\n\nbackend-init-fapi;token-init-pkcs11-tool;token-init-key-import;tools-p11-kit;housekeeping-fapi;\nbackend-init-fapi;token-init-p11tool;token-init-key-import;tools-p11-kit;housekeeping-fapi\n\nbackend-init-fapi;token-init-pkcs11-tool;token-init-key-import;tools-p11tool;housekeeping-fapi;\nbackend-init-fapi;token-init-p11tool;token-init-key-import;tools-p11tool;housekeeping-fapi\n\nbackend-init-fapi;token-init-pkcs11-tool;token-init-key-import;tools-nss-tools;housekeeping-fapi;\nbackend-init-fapi;token-init-p11tool;token-init-key-import;tools-nss-tools;housekeeping-fapi\n--\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfineon%2Fpkcs11-optiga-tpm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finfineon%2Fpkcs11-optiga-tpm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finfineon%2Fpkcs11-optiga-tpm/lists"}