Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TPM2 Tools Context Utility

Utility which will convert a context file between tpm2_tools and the raw structure TPMS_CONTEXT.

TPM specifications describe TPM2 Structure Context Data (pg 146) structure as

imagtes/tpms_context.png

which is used by go-tpm tpm2.ContextSave and tpm2.ContextLoad

However, tpm2_tools context file includes tool-specific headers and values here

    /*
     * Saving the TPMS_CONTEXT structure to disk, format:
     * TPM2.0-TOOLS HEADER
     * U32 hierarchy
     * U32 savedHandle
     * U64 sequence
     * U16 contextBlobLength
     * BYTE[] contextBlob
     */

Which means is if you use tpm2_tools to save a context file, its not compatible with go-tpm.

This utility will help convert basic contexts back and forth

THe follwoing converts

  • tpm2_tools saved context --> go-tpm load context i.,e you create a key with tpm2_tools, save it and then read with go-tpm

  • go-tpm key --> tpm2_tools context i.,e you create a key with go-tpm, save it and then read with tpm2_tools

Limitations:

  • The contexts files currently only support single parent-child keys. A todo is to support context chains
  • Only supports keys (not session contexts)

also see see


Setup

The following uses a softwaretpm

cd example/
#rm -rf myvtpm && mkdir myvtpm  && \
#swtpm_setup --tpmstate myvtpm --tpm2 --create-ek-cert && \
   swtpm socket --tpmstate dir=myvtpm --tpm2 --server type=tcp,port=2321 --ctrl type=tcp,port=2322 --flags not-need-init,startup-clear

export TPM2TOOLS_TCTI="swtpm:port=2321"
export TPM="127.0.0.1:2341" # /dev/tpmrm0

TPM2_TOOLS --> GO-TPM

The follwoing will read a tpm2 generated key file key.ctx, parse it and load it for use with go-tpm.

From there it will use the key to encrypt some data

## first create a an aes key
printf '\x00\x00' > unique.dat
tpm2_createprimary -C o -G ecc  -g sha256  -c primary.ctx -a "fixedtpm|fixedparent|sensitivedataorigin|userwithauth|noda|restricted|decrypt" -u unique.dat

tpm2_create -g sha256 -G aes -u key.pub -r key.priv -C primary.ctx
### save the key as `key.ctx`
tpm2_load -C primary.ctx -u key.pub -r key.priv -n key.name -c key.ctx

### now convert
go run cmd/main.go --mode=from-tpm2  \
   --tpm-path="127.0.0.1:2321"  \
    --contextFileIn=example/keys/key.ctx  \
     --contextFileOut=example/keys/tpm_context.ctx

### now use the key
cd example/
go run from_tpm2_tools/main.go \
   --tpm-path="127.0.0.1:2321" \
   --contextFileIn="keys/tpm_context.ctx"

  Recalled Name 000b7ab4bca0b83ff1627cd9ada2ff83772205d62f4afdc92232fa5cd998069d931d
  IV: 04066b6065e8a2aaccefd921a80396f3
  Encrypted 6fb5aaf543
  Decrypted foooo

GO-TPM --> TPM2_TOOLS

THe following will create an aes key under the H2 parent using go and save the context to go_context.ctx

From there the utility here will read that file and write a tpm2_tools compativle context to key2.ctx

## create a key and save the context to go_context
cd example/
go run to_tpm2_tools/main.go \
   --tpm-path="127.0.0.1:2321" \
   --contextFileOut="keys/go_context.ctx"

go run cmd/main.go --mode=to-tpm2  \
  --tpm-path="127.0.0.1:2321" \
   --parentType=h2  \
   --contextFileIn=example/keys/go_context.ctx  \
   --contextFileOut=example/keys/key2.ctx

Then encrpt/decrypt with both key context

cd keys/
echo -n "foo" > plain.out
openssl rand  -out iv.bin 16

### encrypt with tpm2_tools genreated key.ctx
tpm2_encryptdecrypt --iv iv.bin -c key2.ctx  -o encrypt.out plain.out

## decrypt with converted generated key2.ctx
tpm2_encryptdecrypt --iv iv.bin -c key2.ctx -d -o decrypt.out encrypt.out

In my case the key name had the following specs.

$ tpm2_readpublic -c key.ctx
name: 000b7ab4bca0b83ff1627cd9ada2ff83772205d62f4afdc92232fa5cd998069d931d
qualified name: 000b9194d774c62d5197dc9838a19897a71afee145bfec1b3899e3ac1e80062cc9d9
name-alg:
  value: sha256
  raw: 0xb
attributes:
  value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign
  raw: 0x60072
type:
  value: symcipher
  raw: 0x25
sym-alg:
  value: aes
  raw: 0x6
sym-mode:
  value: null
  raw: 0x10
sym-keybits: 128
symcipher: b5094699172df59db8fe34e925b6935663cbc39c1517baa3e8e32137aac254f2

$ tpm2_print -t TPM2B_PUBLIC key.pub
name-alg:
  value: sha256
  raw: 0xb
attributes:
  value: fixedtpm|fixedparent|sensitivedataorigin|userwithauth|decrypt|sign
  raw: 0x60072
type:
  value: symcipher
  raw: 0x25
sym-alg:
  value: aes
  raw: 0x6
sym-mode:
  value: null
  raw: 0x10
sym-keybits: 128
symcipher: b5094699172df59db8fe34e925b6935663cbc39c1517baa3e8e32137aac254f2

And notice the tpm and go generated keys are of the same size

$ tpm2_print -t TPMS_CONTEXT key.ctx
version: 1
hierarchy: owner
handle: 0x80000000 (2147483648)
sequence: 18
contextBlob: 
	size: 488

$ tpm2_print -t TPMS_CONTEXT key2.ctx
version: 1
hierarchy: owner
handle: 0x80000000 (2147483648)
sequence: 18
contextBlob: 
	size: 488

Parsing TPM2_TOOLS saved context

The context file tpm2_tools uses basically uses this structure

    /*
     * Saving the TPMS_CONTEXT structure to disk, format:
     * TPM2.0-TOOLS HEADER
     * U32 hierarchy
     * U32 savedHandle
     * U64 sequence
     * U16 contextBlobLength
     * BYTE[] contextBlob
     */

Critically, contextBlob is not what go-tpm uses in plain tpm2.ContextSave but a complex structure which includes the raw context info from go-tpm plus values for Esys_ContextSave described below

see the section below for links to tpm2_tools and ESYS_Context

For a specific run of the parsing, consider the tpm2_tools generated context here

$ xxd -p -c 100000 key.ctx 
badcc0de000000014000000180000000000000000000000201e80000000001800040112315c7b03d188040c4f4c550072c62547e5dfbf9ef83ccbaa59c40ce39a175b1d4dd0db1c034041401d3e8a6144f9fc720b4569b9bdeca5c47921d213608658931209745c4e7a610e3d65b8298056c6e251b7f357b0eaaf6505b64d6b8b0271979222e7b00f66bb55c9d1f6b075826bcd20d6da3c25d16280bda5bd74da4d83f9ade38f0e59cc1194e449a9a9349b8e195131c344adf57316c283ca6db9542a7222486a62e6c86a7b8306b9586faadae8518d0bda91ef4dfe04c797dee22e82350cf9fce1527ea2df47fd815e719e16c46fae353783347ade5753b2d77bdb4809a2f839de6a40f8263c5ec6df3447752fcc2217734dc02590ce40a93323d26ffba614662111591efa338c449cdb2f552f70014bde332f06f1511cec75d7e335078802377d7d775f486089e154a61ca4b86afb3c137e09d1706637392401ec5eb4252d130e974f235e1ee4b2089ec997c343ab12895e731e469957d08637e0cabb919311ced2cc98f6dd72ffaaa214de944d0357e44176657daeb2ef2d70000800000010022000b03f4e82d95cc2f50f3afda79980356ca8ca9b83d47231c15d7571b4669f9e6770000000100320025000b0006007200000006008000100020dc24075e84cea2fbc7d5302b3719aff39412a4051cb55c44a69bacb03993cae9

which you can breadk down as:

* magic: `badcc0de`   // static const UINT32 MAGIC = 0xBADCC0DE;
* version: `00000001`   // #define CONTEXT_VERSION 1
* hierarch: `40000001`
* savedHandle `80000000`  
* sequence `0000000000000002`
* length (contextblob+metadata)   `01e8`  length 488
* context blob + metadata:
    context struct
      0000  // always 0
      00000180 // size 384
      0040112315c7b03d188040c4f4c550072c62547e5dfbf9ef83ccbaa59c40ce39a175b1d4dd0db1c034041401d3e8a6144f9fc720b4569b9bdeca5c47921d213608658931209745c4e7a610e3d65b8298056c6e251b7f357b0eaaf6505b64d6b8b0271979222e7b00f66bb55c9d1f6b075826bcd20d6da3c25d16280bda5bd74da4d83f9ade38f0e59cc1194e449a9a9349b8e195131c344adf57316c283ca6db9542a7222486a62e6c86a7b8306b9586faadae8518d0bda91ef4dfe04c797dee22e82350cf9fce1527ea2df47fd815e719e16c46fae353783347ade5753b2d77bdb4809a2f839de6a40f8263c5ec6df3447752fcc2217734dc02590ce40a93323d26ffba614662111591efa338c449cdb2f552f70014bde332f06f1511cec75d7e335078802377d7d775f486089e154a61ca4b86afb3c137e09d1706637392401ec5eb4252d130e974f235e1ee4b2089ec997c343ab12895e731e469957d08637e0cabb919311ced2cc98f6dd72ffaaa214de944d0357e44176657daeb2ef2d7  // contextblob of size 384

    metadata

      0000 /**< size of the operand buffer */
      80000001 /**< Handle used by TPM */
      0022  // length = 34
      000b03f4e82d95cc2f50f3afda79980356ca8ca9b83d47231c15d7571b4669f9e677 /**< TPM name of the object */
      00000001        /**< Selector for resource type */  #define IESYSC_KEY_RSRC                1    /**< Tag for key resource */'
      0032  // len public
      0025000b0006007200000006008000100020dc24075e84cea2fbc7d5302b3719aff39412a4051cb55c44a69bacb03993cae9  // public tpm2b

note the public key:

$ xxd -p -c 1000 key.pub 

00320025000b0006007200000006008000100020dc24075e84cea2fbc7d5302b3719aff39412a4051cb55c44a69bacb03993cae9

ESYS Context

10.13 Esys_ContextSave Commands

If the ESYS_TR object being saved refers to a session, the ESYS_TR object is invalidated.
This means that the ESYS_TR object cannot be used for any future operations and the variable can be
discarded.

Futhermore, the ESAPI implementation augments the data inside the saved context blob by the metadata
it requires for e.g. object names, if needed. This is done by augmenting the contents of context-
>contextBlob.buffer (and size). This data is used to restore the ESYS_TR object during ContextLoad.
NOTE: authorization values kept inside the ESYS_TR object metadata shall not be stored in the context
blobs.

The recommended implementation is:

typedef TPM2B_EVENT TSS2B_METADATA;
typedef struct {
 UINT32 reserved; /* Must always be zero */
 TPM2B_CONTEXT_DATA tpmContext;
 TPM2B_METADATA esysMetadata;
} ESYS_CONTEXT_DATA;
if (e.g. type == RSA_KEY && type != HashSequence) {
 ESYS_CONTEXT_DATA esyscontextData;
 esyscontextData.reserved = 0;
 esyscontextData.tpmContext.buffer = context->contextBlob.buffer;
 esyscontextData.tpmContext.size = context->contextBlob.size;
 esyscontextData.esysMetadata.buffer = metadata;
 esyscontextData.esysMetadata.size = metadata_size;
 context->contextBlob.buffer = esyscontextData;
 context->contextBlob.size = sizeof(UINT32) +
 sizeof(UINT16) + esyscontextData.tpmContext.size +
 sizeof(UINT16) + esyscontextData.esysMetadata.size;
}

in tpm2_tools

/**  Esys resource with size field
 */
typedef struct {
    UINT16                                         size;    /**< size of the operand buffer */
    IESYS_RESOURCE                                 data;    /**< Esys resource data */

} IESYS_METADATA;


/** Type for representing TPM-Resource
 */
typedef struct {
    TPM2_HANDLE                                  handle;    /**< Handle used by TPM */
    TPM2B_NAME                                     name;    /**< TPM name of the object */
    IESYSC_RESOURCE_TYPE                       rsrcType;    /**< Selector for resource type */
    IESYS_RSRC_UNION                               misc;    /**< Resource specific information */
} IESYS_RESOURCE;

#define IESYSC_KEY_RSRC                1    /**< Tag for key resource */'

About

TPM2 Tools Context Utility

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages