keyfile

package module
v0.0.0-...-04534a2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 7, 2024 License: MIT Imports: 27 Imported by: 22

README

go-tpm-keyfile

Implements the ASN.1 Specification for TPM 2.0 Key Files.

https://www.hansenpartnership.com/draft-bottomley-tpm2-keys.html

Implementation Status
  • Loadable Keys
  • Importable Keys
  • Sealed data

Loadable Keys

With NewLoadableKey

package main

import (
	"os"

	keyfile "github.com/foxboron/go-tpm-keyfiles"

	"github.com/google/go-tpm/tpm2"
	"github.com/google/go-tpm/tpm2/transport/simulator"
)

func main() {
	tpm, _ := simulator.OpenSimulator()
	defer tpm.Close()
	k, _ := keyfile.NewLoadableKey(tpm, tpm2.TPMAlgECC, 256, []byte{},
		keyfile.WithDescription("TPM Key"),
	)
	os.Writefile("key.pem", k.Bytes(), 0640)
}

With NewTPMKey

package main

import (
	"os"

	keyfile "github.com/foxboron/go-tpm-keyfiles"

	"github.com/google/go-tpm/tpm2"
	"github.com/google/go-tpm/tpm2/transport/simulator"
)

func main(){
	tpm, _ := simulator.OpenSimulator()
	defer tpm.Close()

	primary, _ := tpm2.CreatePrimary{
		PrimaryHandle: tpm2.TPMRHOwner,
		InPublic:      tpm2.New2B(tpm2.ECCSRKTemplate),
	}.Execute(tpm)

	eccTemplate := tpm2.TPMTPublic{
		Type:    tpm2.TPMAlgECC,
		NameAlg: sha,
		ObjectAttributes: tpm2.TPMAObject{
			SignEncrypt:         true,
			FixedTPM:            true,
			FixedParent:         true,
			SensitiveDataOrigin: true,
			UserWithAuth:        true,
		},
		Parameters: tpm2.NewTPMUPublicParms(
			tpm2.TPMAlgECC,
			&tpm2.TPMSECCParms{
				CurveID: ecc,
				Scheme: tpm2.TPMTECCScheme{
					Scheme: tpm2.TPMAlgNull,
				},
			},
		),
	}

	eccKeyResponse, := tpm2.CreateLoaded{
		ParentHandle: tpm2.AuthHandle{
			Handle: primary.ObjectHandle,
			Name:   primary.Name,
			Auth:   tpm2.PasswordAuth([]byte(nil)),
		},
		InPublic: tpm2.New2BTemplate(&eccTemplate),
	}.Execute(tpm)

	k := keyfile.NewTPMKey(
		keyfile.OIDOldLoadableKey
		eccKeyResponse.OutPublic,
		eccKeyResponse.OutPrivate,
		keyfile.WithDescription("This is a TPM Key"),
	)

	os.Writefile("key.pem", k.Bytes(), 0640)
}

TPMSigner

go-tpm-keyfile implements a crypto.Signer interface to be used with the keys for easy signature creation and verification.

The TPMKeySigner struct implements a callback-style approach for user auth, owner auth and for TPM fetching for easier implementation towards things that require user-input.

package main

import (
	"crypto"
	"os"

	keyfile "github.com/foxboron/go-tpm-keyfiles"

	"github.com/google/go-tpm/tpm2"
	"github.com/google/go-tpm/tpm2/transport/simulator"
)

func main() {
	tpm, _ := simulator.OpenSimulator()
	defer tpm.Close()

	k, _ := NewLoadableKey(tpm, tpm2.TPMAlgECC, 256, []byte(""))

	signer, _ := k.Signer(tpm, []byte(""), []byte(""))

	h := crypto.SHA256.New()
	h.Write([]byte("message"))
	b := h.Sum(nil)

	sig, _ := signer.Sign((io.Reader)(nil), b[:], crypto.SHA256)

	ok, err := k.Verify(crypto.SHA256, b[:], sig)
	if !ok || err != nil {
		log.Fatalf("invalid signature")
	}
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	OIDOldLoadableKey = encasn1.ObjectIdentifier{2, 23, 133, 10, 2}

	// id-loadablekey OBJECT IDENTIFIER ::=  {id-tpmkey 3}
	OIDLoadableKey = encasn1.ObjectIdentifier{2, 23, 133, 10, 1, 3}

	// id-importablekey OBJECT IDENTIFIER ::=  {id-tpmkey 4}
	OIDImportableKey = encasn1.ObjectIdentifier{2, 23, 133, 10, 1, 4}

	// id-sealedkey OBJECT IDENTIFIER ::= {id-tpmkey 5}
	OIDSealedKey = encasn1.ObjectIdentifier{2, 23, 133, 10, 1, 5}
)
View Source
var (
	TPM_HT_NV_INDEX       uint32 = 0x01
	TPM_HT_POLICY_SESSION uint32 = 0x03
	TPM_HT_PERMANENT      uint32 = 0x40
	TPM_HT_TRANSIENT      uint32 = 0x80
	TPM_HT_PERSISTENT     uint32 = 0x81
)
View Source
var (
	// If a permanent handle (MSO 0x40) is specified then the implementation MUST run
	// TPM2_CreatePrimary on the handle using the TCG specified Elliptic Curve
	// template [TCG-Provision] (section 7.5.1 for the Storage and other seeds or
	// 7.4.1 for the endorsement seed) which refers to the TCG EK Credential Profile
	// [TCG-EK-Profile] . Since there are several possible templates, implementations
	// MUST always use the H template (the one with zero size unique fields). The
	// template used MUST be H-2 (EK Credential Profile section B.4.5) for the NIST
	// P-256 curve if rsaParent is absent or the H-1 (EK Credential Profile section
	// B.4.4) RSA template with a key length of 2048 if rsaParent is present and true
	// and use the primary key so generated as the parent.
	ECCSRK_H2_Template = tpm2.TPMTPublic{
		Type:    tpm2.TPMAlgECC,
		NameAlg: tpm2.TPMAlgSHA256,
		ObjectAttributes: tpm2.TPMAObject{
			FixedTPM:            true,
			FixedParent:         true,
			SensitiveDataOrigin: true,
			UserWithAuth:        true,
			NoDA:                true,
			Restricted:          true,
			Decrypt:             true,
		},
		Parameters: tpm2.NewTPMUPublicParms(
			tpm2.TPMAlgECC,
			&tpm2.TPMSECCParms{
				Symmetric: tpm2.TPMTSymDefObject{
					Algorithm: tpm2.TPMAlgAES,
					KeyBits: tpm2.NewTPMUSymKeyBits(
						tpm2.TPMAlgAES,
						tpm2.TPMKeyBits(128),
					),
					Mode: tpm2.NewTPMUSymMode(
						tpm2.TPMAlgAES,
						tpm2.TPMAlgCFB,
					),
				},
				CurveID: tpm2.TPMECCNistP256,
			},
		),
		Unique: tpm2.NewTPMUPublicID(
			tpm2.TPMAlgECC,
			&tpm2.TPMSECCPoint{
				X: tpm2.TPM2BECCParameter{
					Buffer: make([]byte, 0),
				},
				Y: tpm2.TPM2BECCParameter{
					Buffer: make([]byte, 0),
				},
			},
		),
	}
)
View Source
var (
	ErrNotTPMKey = errors.New("not a TSS2 PRIVATE KEY")
)

Errors

Functions

func ChangeAuth

func ChangeAuth(tpm transport.TPMCloser, ownerauth []byte, key *TPMKey, oldpin, newpin []byte) error

ChangeAuth changes the object authn header to something else notice this changes the private blob inside the key in-place.

func CreateKey

func CreateKey(sess *TPMSession, keytype tpm2.TPMAlgID, bits int, ownerAuth []byte, auth []byte) (tpm2.TPM2BPublic, tpm2.TPM2BPrivate, error)

TODO: Private until I'm confident of the API

func CreateSRK

func CreateSRK(sess *TPMSession, hier tpm2.TPMHandle, ownerAuth []byte) (*tpm2.AuthHandle, *tpm2.TPMTPublic, error)

Creates a Storage Key, or return the loaded storage key

func DeriveECDH

func DeriveECDH(sess *TPMSession, key *TPMKey, sessionkey *ecdh.PublicKey, ownerauth, auth []byte) ([]byte, error)

func Encode

func Encode(out io.Writer, key *TPMKey) error

func FlushHandle

func FlushHandle(tpm transport.TPM, h handle)

Helper to flush handles

func GetParentHandle

func GetParentHandle(sess *TPMSession, parent tpm2.TPMHandle, ownerauth []byte) (*tpm2.AuthHandle, error)

This looks at the passed parent defined in a TPMKey and gives back the appropriate handle to load our TPM key under. With a PERMANENT handle it will load an transient SRK under the parent heier, and give back the handle. With a TRANSIENT handle it will load a transient SRK under the Owner hier, and hand back the handle. With a PERSISTENT handle it will try to read the public portion of the key.

This function will also set the appropriate bound HMAC session to the returned keys.

func IsMSO

func IsMSO(handle tpm2.TPMHandle, mso uint32) bool

func LoadKey

func LoadKey(sess *TPMSession, key *TPMKey, ownerauth []byte) (keyhandle *tpm2.AuthHandle, parenthandle *tpm2.AuthHandle, err error)

func LoadKeyWithParent

func LoadKeyWithParent(session *TPMSession, parent tpm2.AuthHandle, key *TPMKey) (*tpm2.AuthHandle, error)

func Marshal

func Marshal(key *TPMKey) []byte

func ReadPublic

func ReadPublic(tpm transport.TPMCloser, handle tpm2.TPMHandle) (*tpm2.AuthHandle, *tpm2.TPMTPublic, error)

func Sign

func Sign(sess *TPMSession, key *TPMKey, ownerauth, auth, digest []byte, digestalgo tpm2.TPMAlgID) (*tpm2.TPMTSignature, error)

func SignASN1

func SignASN1(sess *TPMSession, key *TPMKey, ownerauth, auth, digest []byte, digestalgo tpm2.TPMAlgID) ([]byte, error)

func SupportedECCAlgorithms

func SupportedECCAlgorithms(tpm transport.TPMCloser) []int

func UnsealData

func UnsealData(tpm transport.TPMCloser, key *TPMKey, ownerauth []byte) ([]byte, error)

Types

type TPMAuthPolicy

type TPMAuthPolicy struct {
	Name   string
	Policy []*TPMPolicy
}

type TPMKey

type TPMKey struct {
	Keytype     encasn1.ObjectIdentifier
	EmptyAuth   bool
	Policy      []*TPMPolicy
	Secret      tpm2.TPM2BEncryptedSecret
	AuthPolicy  []*TPMAuthPolicy
	Description string
	Parent      tpm2.TPMHandle
	Pubkey      tpm2.TPM2BPublic
	Privkey     tpm2.TPM2BPrivate
	// contains filtered or unexported fields
}

func Decode

func Decode(b []byte) (*TPMKey, error)

func ImportTPMKey

func ImportTPMKey(tpm transport.TPMCloser, key *TPMKey, ownerauth []byte) (*TPMKey, error)

Returns a loadable key

func NewImportablekey

func NewImportablekey(rempub *tpm2.TPMTPublic, pk any, fn ...TPMKeyOption) (*TPMKey, error)

func NewLoadableKey

func NewLoadableKey(tpm transport.TPMCloser, alg tpm2.TPMAlgID, bits int, ownerauth []byte, fn ...TPMKeyOption) (*TPMKey, error)

NewLoadableKey creates a new LoadableKey

func NewLoadableKeyWithResponse

func NewLoadableKeyWithResponse(tpm transport.TPMCloser, alg tpm2.TPMAlgID, bits int, ownerauth []byte, fn ...TPMKeyOption) (*TPMKey, *tpm2.CreateResponse, error)

NewLoadableKeyWithResponse creates a new LoadableKey and returns the tpm2.CreateResponse

func NewSealedData

func NewSealedData(tpm transport.TPMCloser, data []byte, ownerauth []byte, fn ...TPMKeyOption) (*TPMKey, error)

func NewTPMKey

func NewTPMKey(oid encasn1.ObjectIdentifier, pubkey tpm2.TPM2BPublic, privkey tpm2.TPM2BPrivate, fn ...TPMKeyOption) *TPMKey

func Parse

func Parse(b []byte) (*TPMKey, error)

func (*TPMKey) AddOptions

func (t *TPMKey) AddOptions(fn ...TPMKeyOption)

func (*TPMKey) Bytes

func (t *TPMKey) Bytes() []byte

func (*TPMKey) Derive

func (t *TPMKey) Derive(tpm transport.TPMCloser, sessionkey *ecdh.PublicKey, ownerAuth, auth []byte) ([]byte, error)

func (*TPMKey) HasAuth

func (t *TPMKey) HasAuth() bool

func (*TPMKey) HasSigner

func (t *TPMKey) HasSigner() bool

func (*TPMKey) KeyAlgo

func (t *TPMKey) KeyAlgo() tpm2.TPMAlgID

func (*TPMKey) KeySize

func (t *TPMKey) KeySize() int

func (*TPMKey) PublicKey

func (t *TPMKey) PublicKey() (crypto.PublicKey, error)

PublicKey returns the ecdsa.Publickey or rsa.Publickey of the TPMKey

func (*TPMKey) Signer

func (t *TPMKey) Signer(tpm transport.TPMCloser, ownerAuth, auth []byte) (crypto.Signer, error)

Wraps TPMSigner with some sane defaults Use NewTPMSigner if you need more control of the parameters

func (*TPMKey) Verify

func (t *TPMKey) Verify(alg crypto.Hash, hashed []byte, sig []byte) (bool, error)

type TPMKeyOption

type TPMKeyOption func(key *TPMKey)

func WithAuthPolicy

func WithAuthPolicy(authpolicy []*TPMAuthPolicy) TPMKeyOption

func WithDescription

func WithDescription(desc string) TPMKeyOption

func WithKeytype

func WithKeytype(keytype asn1.ObjectIdentifier) TPMKeyOption

func WithParent

func WithParent(parent tpm2.TPMHandle) TPMKeyOption

func WithPolicy

func WithPolicy(policy []*TPMPolicy) TPMKeyOption

func WithPrivkey

func WithPrivkey(privkey tpm2.TPM2BPrivate) TPMKeyOption

func WithPubkey

func WithPubkey(pubkey tpm2.TPM2BPublic) TPMKeyOption

func WithSecret

func WithSecret(secret tpm2.TPM2BEncryptedSecret) TPMKeyOption

func WithUserAuth

func WithUserAuth(userauth []byte) TPMKeyOption

type TPMKeySigner

type TPMKeySigner struct {
	// contains filtered or unexported fields
}

TPMKeySigner implements the crypto.Signer interface for TPMKey It allows passing callbacks for TPM, ownerAuth and user auth.

func NewTPMKeySigner

func NewTPMKeySigner(k *TPMKey, ownerAuth func() ([]byte, error), tpm func() transport.TPMCloser, auth func(*TPMKey) ([]byte, error)) *TPMKeySigner

func (*TPMKeySigner) Public

func (t *TPMKeySigner) Public() crypto.PublicKey

Returns the crypto.PublicKey

func (*TPMKeySigner) Sign

func (t *TPMKeySigner) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error)

Sign implementation

type TPMPolicy

type TPMPolicy struct {
	CommandCode   int
	CommandPolicy []byte
}

type TPMSession

type TPMSession struct {
	// contains filtered or unexported fields
}

This is a helper to deal with TPM Session encryption.

func NewTPMSession

func NewTPMSession(tpm transport.TPMCloser) *TPMSession

func (*TPMSession) FlushHandle

func (t *TPMSession) FlushHandle()

func (*TPMSession) GetHMAC

func (t *TPMSession) GetHMAC() tpm2.Session

func (*TPMSession) GetHMACIn

func (t *TPMSession) GetHMACIn() tpm2.Session

func (*TPMSession) GetHMACOut

func (t *TPMSession) GetHMACOut() tpm2.Session

func (*TPMSession) GetTPM

func (t *TPMSession) GetTPM() transport.TPMCloser

func (*TPMSession) SetOpt

func (t *TPMSession) SetOpt(opt tpm2.AuthOption)

func (*TPMSession) SetSalted

func (t *TPMSession) SetSalted(handle tpm2.TPMHandle, pub tpm2.TPMTPublic)

func (*TPMSession) SetTPM

func (t *TPMSession) SetTPM(tpm transport.TPMCloser)

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL