From 5d3c0cfcd075b1a626096e16abda2288a82935d0 Mon Sep 17 00:00:00 2001 From: Mariano Cano Date: Thu, 2 Nov 2023 15:21:11 -0700 Subject: [PATCH] Fix comments from code review This commit also adds a way to define the SRK template used to load the blobs into the TPM. --- tpm/tss2/encode.go | 15 ++++---- tpm/tss2/encode_test.go | 1 - tpm/tss2/signer.go | 81 ++++++++++++++++++++++++++++++----------- tpm/tss2/signer_test.go | 11 ++++-- 4 files changed, 73 insertions(+), 35 deletions(-) diff --git a/tpm/tss2/encode.go b/tpm/tss2/encode.go index df5b50e1..5888c1c2 100644 --- a/tpm/tss2/encode.go +++ b/tpm/tss2/encode.go @@ -1,10 +1,9 @@ package tss2 -import ( - "encoding/pem" +import "encoding/pem" - "github.com/google/go-tpm/legacy/tpm2" -) +// handle owner is the reserver handler TPM_RH_OWNER. +const handleOwner = 0x40000001 // TPMOption is the type used to modify a [TPMKey]. type TPMOption func(*TPMKey) @@ -14,9 +13,9 @@ func New(pub, priv []byte, opts ...TPMOption) *TPMKey { key := &TPMKey{ Type: oidLoadableKey, EmptyAuth: true, - Parent: int(tpm2.HandleOwner), - PublicKey: integrityPrefix(pub), - PrivateKey: integrityPrefix(priv), + Parent: handleOwner, + PublicKey: addPrefixLength(pub), + PrivateKey: addPrefixLength(priv), } for _, fn := range opts { fn(key) @@ -56,7 +55,7 @@ func EncodeToMemory(pub, priv []byte, opts ...TPMOption) ([]byte, error) { return New(pub, priv, opts...).EncodeToMemory() } -func integrityPrefix(b []byte) []byte { +func addPrefixLength(b []byte) []byte { s := len(b) return append([]byte{byte(s >> 8 & 0xFF), byte(s & 0xFF)}, b...) } diff --git a/tpm/tss2/encode_test.go b/tpm/tss2/encode_test.go index 8bdfe451..df486748 100644 --- a/tpm/tss2/encode_test.go +++ b/tpm/tss2/encode_test.go @@ -95,7 +95,6 @@ MCgGBmeBBQoBA6ADAQH/AgRAAAABBAgABnB1YmxpYwQJAAdwcml2YXRl got, err := tt.tpmKey.EncodeToMemory() tt.assertion(t, err) assert.Equal(t, tt.want, got) - t.Log(string(got)) }) } } diff --git a/tpm/tss2/signer.go b/tpm/tss2/signer.go index 90225480..bb4e159b 100644 --- a/tpm/tss2/signer.go +++ b/tpm/tss2/signer.go @@ -31,33 +31,55 @@ import ( "github.com/google/go-tpm/tpmutil" ) -var primaryParams = tpm2.Public{ - Type: tpm2.AlgECC, - NameAlg: tpm2.AlgSHA256, - Attributes: tpm2.FlagStorageDefault, - ECCParameters: &tpm2.ECCParams{ - Symmetric: &tpm2.SymScheme{ - Alg: tpm2.AlgAES, - KeyBits: 128, - Mode: tpm2.AlgCFB, +var ( + // ECCSRKTemplate contains the TCG reference ECC-P256 SRK template. + // https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf + ECCSRKTemplate = tpm2.Public{ + Type: tpm2.AlgECC, + NameAlg: tpm2.AlgSHA256, + Attributes: tpm2.FlagStorageDefault | tpm2.FlagNoDA, + ECCParameters: &tpm2.ECCParams{ + Symmetric: &tpm2.SymScheme{ + Alg: tpm2.AlgAES, + KeyBits: 128, + Mode: tpm2.AlgCFB, + }, + Sign: &tpm2.SigScheme{ + Alg: tpm2.AlgNull, + }, + CurveID: tpm2.CurveNISTP256, }, - Sign: &tpm2.SigScheme{ - Alg: tpm2.AlgNull, + } + + // RSASRKTemplate contains the TCG reference RSA-2048 SRK template. + // https://trustedcomputinggroup.org/wp-content/uploads/TCG-TPM-v2.0-Provisioning-Guidance-Published-v1r1.pdf + RSASRKTemplate = tpm2.Public{ + Type: tpm2.AlgRSA, + NameAlg: tpm2.AlgSHA256, + Attributes: tpm2.FlagStorageDefault | tpm2.FlagNoDA, + RSAParameters: &tpm2.RSAParams{ + Symmetric: &tpm2.SymScheme{ + Alg: tpm2.AlgAES, + KeyBits: 128, + Mode: tpm2.AlgCFB, + }, + ModulusRaw: make([]byte, 256), + KeyBits: 2048, }, - CurveID: tpm2.CurveNISTP256, - }, -} + } +) // Signer implements [crypto.Signer] using a [TPMKey]. type Signer struct { - rw io.ReadWriter - publicKey crypto.PublicKey - tpmKey *TPMKey + rw io.ReadWriter + publicKey crypto.PublicKey + tpmKey *TPMKey + srkTemplate tpm2.Public } // CreateSigner creates a new [crypto.Signer] with the given TPM (rw) and // [TPMKey]. The caller is responsible of opening and closing the TPM. -func CreateSigner(rw io.ReadWriter, key *TPMKey) (crypto.Signer, error) { +func CreateSigner(rw io.ReadWriter, key *TPMKey) (*Signer, error) { switch { case rw == nil: return nil, fmt.Errorf("invalid TPM channel: rw cannot be nil") @@ -90,12 +112,27 @@ func CreateSigner(rw io.ReadWriter, key *TPMKey) (crypto.Signer, error) { } return &Signer{ - rw: rw, - publicKey: publicKey, - tpmKey: key, + rw: rw, + publicKey: publicKey, + tpmKey: key, + srkTemplate: RSASRKTemplate, }, nil } +// SetSRKTemplate allows to change the Storage Primary Key (SRK) template used +// to load the the public/private blobs into an object in the TPM. +// +// It currently defaults to [RSASRKTemplate], the same used ad default in the +// [go.step.sm/crypto/tpm] package. +// +// # Experimental +// +// Notice: This API is EXPERIMENTAL and may be changed or removed in a later +// release. +func (s *Signer) SetSRKTemplate(p tpm2.Public) { + s.srkTemplate = p +} + func (s *Signer) Public() crypto.PublicKey { return s.publicKey } @@ -103,7 +140,7 @@ func (s *Signer) Public() crypto.PublicKey { func (s *Signer) Sign(_ io.Reader, digest []byte, opts crypto.SignerOpts) (signature []byte, err error) { parentHandle := tpmutil.Handle(s.tpmKey.Parent) if !handleIsPersistent(s.tpmKey.Parent) { - parentHandle, _, err = tpm2.CreatePrimary(s.rw, parentHandle, tpm2.PCRSelection{}, "", "", primaryParams) + parentHandle, _, err = tpm2.CreatePrimary(s.rw, parentHandle, tpm2.PCRSelection{}, "", "", s.srkTemplate) if err != nil { return nil, fmt.Errorf("error creating primary: %w", err) } diff --git a/tpm/tss2/signer_test.go b/tpm/tss2/signer_test.go index 5b36d7de..5dce3446 100644 --- a/tpm/tss2/signer_test.go +++ b/tpm/tss2/signer_test.go @@ -60,7 +60,7 @@ func TestSign(t *testing.T) { assert.NoError(t, rw.Close()) }) - keyHnd, _, err := tpm2.CreatePrimary(rw, tpm2.HandleOwner, tpm2.PCRSelection{}, "", "", primaryParams) + keyHnd, _, err := tpm2.CreatePrimary(rw, tpm2.HandleOwner, tpm2.PCRSelection{}, "", "", ECCSRKTemplate) require.NoError(t, err) t.Cleanup(func() { assert.NoError(t, tpm2.FlushContext(rw, keyHnd)) @@ -85,6 +85,9 @@ func TestSign(t *testing.T) { signer, err := CreateSigner(rw, New(pub, priv)) require.NoError(t, err) + // Set the ECC SRK template used for testing. + signer.SetSRKTemplate(ECCSRKTemplate) + hash := crypto.SHA256.New() hash.Write([]byte("rulingly-quailed-cloacal-indifferentist-roughhoused-self-mad")) sum := hash.Sum(nil) @@ -139,11 +142,11 @@ func TestCreateSigner(t *testing.T) { tests := []struct { name string args args - want crypto.Signer + want *Signer assertion assert.ErrorAssertionFunc }{ {"ok", args{&rw, key}, &Signer{ - rw: &rw, publicKey: publicKey, tpmKey: key, + rw: &rw, publicKey: publicKey, tpmKey: key, srkTemplate: RSASRKTemplate, }, assert.NoError}, {"fail rw", args{nil, key}, nil, assert.Error}, {"fail type", args{&rw, modKey(func(k *TPMKey) { @@ -186,7 +189,7 @@ func TestCreateSigner(t *testing.T) { } b, err := p.Encode() if assert.NoError(t, err) { - k.PublicKey = integrityPrefix(b) + k.PublicKey = addPrefixLength(b) } })}, nil, assert.Error}, }