CREATE_TPM2_KEY(1)
π create_tpm2_key(1) β the manual, but make it cute π
okay so bestie, this is the create_tpm2_key(1) manpage, and it's literally the glow-up guide for making TPM-loadable keys. no cap, it's giving "I need my private key to live inside a TPM" energy, and honestly? iconic.
β¨ NAME β¨
create_tpm2_key β create tpm2 loadable key
πΈ SYNOPSIS πΈ
create_tpm2_key [options] <filename>
π¦ DESCRIPTION π¦
So this command is your main character for creating a TPM-loadable representation of a private key. The key is either internal to the TPM or wrapped from an existing private key. periodt.
okay but here's the tea: this command can now create two different types of keys β importable and loadable (and the default type is loadable, just so you know). The difference is lowkey huge:
- loadable keys require the actual TPM that the key will be loaded on to be present. like, you can't just make one in the void, bestie.
- importable keys can be created without any TPM contact β provided you have the public key of the parent that the new key will be imported to. slay for remote workflows, honestly.
π OPTIONS π
-a,--authβ require a password for the key. default is NO (so no password unless you ask for one).-b,--auth-parent <pwd>β specify the parent key password. default is EmptyAuth.-d,--daβ mark the key as having Dictionary Attack implications. This means if the key password is incorrectly presented too many times, the TPM may implement DA mitigation and refuse connections for a while. so like, don't brute-force your own key, bestie. π-h,--helpβ print this help message. classic.-s,--key-size <size>β key size in bits. default is 2048.-n,--name-scheme <scheme>β name algorithm to use. options aresha1,sha256(the default, in brackets),sha384,sha512. pick your fighter.-p,--parent-handle <handle>β parent for the key. it can either be a persistent key or a hierarchy. the hierarchies can be'platform','owner','null'or'endorsement'. the seeds used for derivation are platform, storage, null or endorsement respectively. iykyk.-v,--versionβ print package version. short and sweet.-w,--wrap <file>β wrap an existing openssl PEM key.<file>can be in either PKCS12 or OpenSSL standard PEM private key form (PKCS1 or PKCS8).-k,--password <pwd>β use this password instead of prompting. no interactive vibe needed.-r,--rsaβ create an RSA key. this is the default, so if you don't say anything, you get RSA. easy.-e,--ecc <curve>β create an ECC key using the specified curve. supported curves arebnp256,nisp256,nisp384. (yes, those spellings are exactly what the manpage says β don't come for me, bestie.)-l,--list-curvesβ list all the Elliptic Curves the TPM supports. honestly obsessed with a discovery option.-c,--key-policyβ specify a policy for the TPM key. policy girlies rise.-i,--import <pubkey>β create an importable key with the outer wrapper encrypted to<pubkey>. this is the remote-workflow queen.--restrictedβ create a restricted key. a restricted key may not be used for general signing or decryption, but it may be the parent of other keys β i.e. it's a storage key. so it's like a key that's only allowed to babysit other keys. respect.-x,--pcr-lock <pcrs>β lock the created key to the specified PCRs by current value. see PCR VALUES for details about formatting. (and yes, that heading is coming right up.)--locality <loc>β can only be used in a set of localities described by the<loc>bitmap. niche but valid.--signed-policy <key>β add a signed policy directive that allows policies signed by the specified public<key>to authorize use of the key. fancy.--secret <handle>β tie authorization of the key to the Authorization of a different object identified by<handle>. more on this in SECRETS IN OTHER OBJECTS, bestie.
π PCR VALUES π
The PCR values are specified as:
<bank>:<list>
Where <bank> is any supported PCR hash bank, and <list> specifies the PCRs to lock the key to as both comma separated individual values as well as comma separated ranges. So:
sha256:1,3
means PCRs 1 and 3 in the sha256 bank. and:
sha512:1,3-5
means PCRs 1, 3, 4 and 5 in the sha512 bank. see? ranges are included. math is mathing. π
π IMPORT π
In some cases, there may be a need to wrap a key without access to the TPM it will be used on. For these cases, an importable key may be specified with the --import option. For this to work, you must use a public key corresponding exactly to the one the importing TPM will use.
note: only Elliptic Curve parents are currently supported. so don't try this with RSA parents yet, bestie. π
For instance, the owner seed elliptic curve storage key may be produced as:
tsscreateprimary -hi o -st -ecc nistp256 -opem parent.pub
Then an importable key may be wrapped to the TPM via:
create_tpm2_key --import parent.pub --wrap key.priv key.tpm
Note that certain parameters must be assumed about a parent when it is wrapped, like:
- the template (must be standard restricted decryption key)
- the name hash (must be
sha256)
so like, you can't just vibe-check your way through this. those assumptions are baked in.
π SECRETS IN OTHER OBJECTS π
When the option --secrets <handle> is used (and yes, the manpage says --secrets here even though the option list spells it --secret β that's the original's vibe, not mine), it creates a key whose authorization password is conditioned on the password of a different object identified by <handle>.
Usually this is a permanent NV index, but could be any object. The design of this policy is to allow the password to be changed without updating the key β simply by changing the authorization of the other object. so you're basically outsourcing the password management. honestly kind of a slay.
BUT. because OpenSSL can only request a single password, keys with a --secret policy may not additionally have an --auth option to also require passing in the password embedded in the key. so don't stack those two, bestie. it's one or the other. periodt.
β SIGNED POLICIES β
When the option --signed-policy <key> is used, it creates a key whose policy can be extended by anyone possessing the private part of <key>. The <key> presented must be a public key β so the owner of the private key doesn't have to be the owner of the created tpm key. cute for delegation.
note: keys created with --signed-policy cannot be used until at least one signed policy is added. so like, the key is basically asleep until you feed it a signed policy. don't forget to wake it up. π
π«Ά FILES π«Ά
Policy File Format
The policy file should contain a rule for each line, where rules can be generated for example with the tsspolicymakerpcr tool from IBM TSS.
Example (PolicyPCR):
$ tsspolicymakerpcr -bm 10000 -if policypcr16aaasha256.txt -v -pr -of
policies/policypcr.txt >> policy.txt
where policypcr16aaasha256.txt contains the desired value of PCR 16.
Example (PolicyAuthValue):
$ echo 0000016b >> policy.txt
short, sweet, and to the point. we love a one-liner. πΈ
π₯ EXAMPLES π₯
Create a self-signed cert using the TPM engine
0. Good practice is to generate the RSA version of the primary storage seed and place it at well known location 81000001 (Microsoft Spec). To do this, you need to manipulate the non resource manager interface so the keys aren't lost when the process dies:
# TPM_DEVICE=/dev/tpm0 tsscreateprimary -hi o -st -rsa
Handle 80000000
# TPM_DEVICE=/dev/tpm0 tssevictcontrol -hi o -ho 80000000 -hp 81000001
# TPM_DEVICE=/dev/tpm0 tssflushcontext -ha 80000000
where 80000000 is the handle and is always returned by the first command. You must do the final tssflushcontext otherwise the transient key won't get flushed since you used the non resource manager interface.
note: tsscreateprimary will take a while to run (50s on my laptop) while the TPM derives an RSA key from the primary seed. This long time is why you want to store a permanent copy of the derived key. so like, make a coffee or whatever.
1. Generate an external key and wrap it for the TPM:
$ openssl genrsa 2048 > <private key>
$ create_tpm2_key -w <private key> [-p 81000001] <key file>
note: specifying the parent is optional (and you need to have created it in step 0) but if you leave it out, the key will still end up parented to the primary storage seed and the TPM will have to re-derive the ECC version of that seed each time you use it. so it's a trade-off, bestie.
note: because the RSA private key is sent to the TPM encrypted, the tss has to have access to the public part of the parent key (if you didn't specify a parent, this public part will be created when the parent key is derived from the storage primary seed), so you may need to do tssreadpublic -p 81000001 before it will work. don't skip this and then get mad. π
2. Make the openssl certificate request:
$ openssl req -keyform engine -engine tpm2 -key <key file> -new -x509
-days 365 -out <certfilename>
3. Test using openssl:
$ openssl s_server -cert <certfilename> -www -accept 4433 -keyform
engine -engine tpm2 -key <keyfilename>
Creating an importable key
1. First get the public key of the storage primary seed (as an elliptic curve key):
$ tsscreateprimary -ecc nistp256 -hi o -opem srk.pub
2. Once you have this public key, you can export it anywhere and do the key wrapping:
$ create_tpm2_key --import srk.pub --wrap my_key.priv my_key.tpm
that's it. importable and ready to travel. β¨
π AUTHOR π
Written by James Bottomley <James.Bottomley@HansenPartnership.com>. absolute legend, honestly. π«Ά
π REPORTING BUGS π
Report bugs to <openssl-tpm2-engine@groups.io>. don't be shy, they want to know. π
π COPYRIGHT π
Copyright 2017 by James Bottomley. License LGPL-2.1-only. so like, respect the license, bestie. πΈ
okay so that's literally the whole page. this manual came from create_tpm2_key version 4.3.0, dated August 2024, and the original header/footer was all CREATE_TPM2_KEY(1) β but we made it cute. slay, and happy key-making. π
πβ¨
π¦ where this page comes from
- opensuse-leap 16.0: openssl_tpm2_engine 4.3.0-bp160.1.8 Β· LGPL-2.1-only
- opensuse-leap 16.0: openssl_tpm2_engine 4.3.0-bp160.1.8 Β· LGPL-2.1-only
- opensuse-leap 16.0: openssl_tpm2_engine 4.3.0-bp160.1.8 Β· LGPL-2.1-only
- opensuse-leap 16.0: openssl_tpm2_engine 4.3.0-bp160.1.8 Β· LGPL-2.1-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms