Skip to content

Commit

Permalink
add several commands needed by Google PINT (#305)
Browse files Browse the repository at this point in the history
This change adds the following commands along with tests:

* ActivateCredential
* Clear
* ECDH_ZGen
* NV_Certify
* NV_Increment
* PolicyNV

Makes progress on #278
  • Loading branch information
chrisfenner authored Sep 3, 2022
1 parent 9860756 commit ece7af1
Show file tree
Hide file tree
Showing 12 changed files with 886 additions and 10 deletions.
95 changes: 95 additions & 0 deletions tpm2/commands/activate_credential_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package tpm2

import (
"bytes"
"testing"

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

func TestActivateCredential(t *testing.T) {
thetpm, err := simulator.OpenSimulator()
if err != nil {
t.Fatalf("could not connect to TPM simulator: %v", err)
}
defer thetpm.Close()

ekCreate := CreatePrimary{
PrimaryHandle: tpm.RHEndorsement,
InPublic: tpm2b.Public{
PublicArea: templates.ECCEKTemplate,
},
}

ekCreateRsp, err := ekCreate.Execute(thetpm)
if err != nil {
t.Fatalf("could not generate EK: %v", err)
}
defer func() {
flush := FlushContext{
FlushHandle: ekCreateRsp.ObjectHandle,
}
err := flush.Execute(thetpm)
if err != nil {
t.Fatalf("could not flush EK: %v", err)
}
}()

srkCreate := CreatePrimary{
PrimaryHandle: tpm.RHOwner,
InPublic: tpm2b.Public{
PublicArea: templates.ECCSRKTemplate,
},
}

srkCreateRsp, err := srkCreate.Execute(thetpm)
if err != nil {
t.Fatalf("could not generate SRK: %v", err)
}
defer func() {
flush := FlushContext{
FlushHandle: srkCreateRsp.ObjectHandle,
}
err := flush.Execute(thetpm)
if err != nil {
t.Fatalf("could not flush SRK: %v", err)
}
}()

secret := tpm2b.Digest{Buffer: []byte("Secrets!!!")}

mc := MakeCredential{
Handle: ekCreateRsp.ObjectHandle,
Credential: secret,
ObjectNamae: srkCreateRsp.Name,
}
mcRsp, err := mc.Execute(thetpm)
if err != nil {
t.Fatalf("could not make credential: %v", err)
}

ac := ActivateCredential{
ActivateHandle: NamedHandle{
Handle: srkCreateRsp.ObjectHandle,
Name: srkCreateRsp.Name,
},
KeyHandle: AuthHandle{
Handle: ekCreateRsp.ObjectHandle,
Name: ekCreateRsp.Name,
Auth: Policy(tpm.AlgSHA256, 16, ekPolicy),
},
CredentialBlob: mcRsp.CredentialBlob,
Secret: mcRsp.Secret,
}
acRsp, err := ac.Execute(thetpm)
if err != nil {
t.Fatalf("could not activate credential: %v", err)
}

if !bytes.Equal(acRsp.CertInfo.Buffer, secret.Buffer) {
t.Errorf("want %x got %x", secret.Buffer, acRsp.CertInfo.Buffer)
}
}
155 changes: 154 additions & 1 deletion tpm2/commands/certify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
)

func TestCertify(t *testing.T) {

thetpm, err := simulator.OpenSimulator()
if err != nil {
t.Fatalf("could not connect to TPM simulator: %v", err)
Expand Down Expand Up @@ -275,3 +274,157 @@ func TestCreateAndCertifyCreation(t *testing.T) {
t.Errorf("Signature verification failed: %v", err)
}
}

func TestNVCertify(t *testing.T) {
thetpm, err := simulator.OpenSimulator()
if err != nil {
t.Fatalf("could not connect to TPM simulator: %v", err)
}
defer thetpm.Close()

Auth := []byte("password")

public := tpm2b.Public{
PublicArea: tpmt.Public{
Type: tpm.AlgRSA,
NameAlg: tpm.AlgSHA256,
ObjectAttributes: tpma.Object{
SignEncrypt: true,
Restricted: true,
FixedTPM: true,
FixedParent: true,
SensitiveDataOrigin: true,
UserWithAuth: true,
},
Parameters: tpmu.PublicParms{
RSADetail: &tpms.RSAParms{
Scheme: tpmt.RSAScheme{
Scheme: tpm.AlgRSASSA,
Details: tpmu.AsymScheme{
RSASSA: &tpms.SigSchemeRSASSA{
HashAlg: tpm.AlgSHA256,
},
},
},
KeyBits: 2048,
},
},
},
}

createPrimarySigner := CreatePrimary{
PrimaryHandle: tpm.RHOwner,
InSensitive: tpm2b.SensitiveCreate{
Sensitive: tpms.SensitiveCreate{
UserAuth: tpm2b.Auth{
Buffer: Auth,
},
},
},
InPublic: public,
}
rspSigner, err := createPrimarySigner.Execute(thetpm)
if err != nil {
t.Fatalf("Failed to create primary: %v", err)
}
flushContextSigner := FlushContext{FlushHandle: rspSigner.ObjectHandle}
defer flushContextSigner.Execute(thetpm)

def := NVDefineSpace{
AuthHandle: tpm.RHOwner,
PublicInfo: tpm2b.NVPublic{
NVPublic: tpms.NVPublic{
NVIndex: tpm.Handle(0x0180000F),
NameAlg: tpm.AlgSHA256,
Attributes: tpma.NV{
OwnerWrite: true,
OwnerRead: true,
AuthWrite: true,
AuthRead: true,
NT: tpm.NTOrdinary,
NoDA: true,
},
DataSize: 4,
},
},
}
if err := def.Execute(thetpm); err != nil {
t.Fatalf("Calling TPM2_NV_DefineSpace: %v", err)
}

readPub := NVReadPublic{
NVIndex: tpm.Handle(0x0180000F),
}
nvPub, err := readPub.Execute(thetpm)
if err != nil {
t.Fatalf("Calling TPM2_NV_ReadPublic: %v", err)
}

prewrite := NVWrite{
AuthHandle: AuthHandle{
Handle: def.PublicInfo.NVPublic.NVIndex,
Name: nvPub.NVName,
Auth: PasswordAuth(nil),
},
NVIndex: NamedHandle{
Handle: def.PublicInfo.NVPublic.NVIndex,
Name: nvPub.NVName,
},
Data: tpm2b.MaxNVBuffer{
Buffer: []byte{0x01, 0x02, 0x03, 0x04},
},
Offset: 0,
}
if err := prewrite.Execute(thetpm); err != nil {
t.Errorf("Calling TPM2_NV_Write: %v", err)
}

nvPub, err = readPub.Execute(thetpm)
if err != nil {
t.Fatalf("Calling TPM2_NV_ReadPublic: %v", err)
}

nvCertify := NVCertify{
AuthHandle: AuthHandle{
Handle: tpm.Handle(0x0180000F),
Name: nvPub.NVName,
Auth: PasswordAuth(nil),
},
SignHandle: AuthHandle{
Handle: rspSigner.ObjectHandle,
Name: rspSigner.Name,
Auth: PasswordAuth(Auth),
},
NVIndex: NamedHandle{
Handle: tpm.Handle(0x0180000F),
Name: nvPub.NVName,
},
QualifyingData: tpm2b.Data{
Buffer: []byte("nonce"),
},
}
rspCert, err := nvCertify.Execute(thetpm)
if err != nil {
t.Fatalf("Failed to certify: %v", err)
}

info, err := Marshal(rspCert.CertifyInfo.AttestationData)
if err != nil {
t.Fatalf("Failed to marshal: %v", err)
}

attestHash := sha256.Sum256(info)
pub := rspSigner.OutPublic.PublicArea
rsaPub, err := helpers.RSAPub(pub.Parameters.RSADetail, pub.Unique.RSA)
if err != nil {
t.Fatalf("Failed to retrieve Public Key: %v", err)
}

if err := rsa.VerifyPKCS1v15(rsaPub, crypto.SHA256, attestHash[:], rspCert.Signature.Signature.RSASSA.Sig.Buffer); err != nil {
t.Errorf("Signature verification failed: %v", err)
}

if !cmp.Equal([]byte("nonce"), rspCert.CertifyInfo.AttestationData.ExtraData.Buffer) {
t.Errorf("Attested buffer is different from original buffer")
}
}
64 changes: 64 additions & 0 deletions tpm2/commands/clear_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package tpm2

import (
"bytes"
"testing"

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

func TestClear(t *testing.T) {
thetpm, err := simulator.OpenSimulator()
if err != nil {
t.Fatalf("could not connect to TPM simulator: %v", err)
}
defer thetpm.Close()

srkCreate := CreatePrimary{
PrimaryHandle: tpm.RHOwner,
InPublic: tpm2b.Public{
PublicArea: templates.ECCSRKTemplate,
},
}

srkCreateRsp, err := srkCreate.Execute(thetpm)
if err != nil {
t.Fatalf("could not generate SRK: %v", err)
}

srkName1 := srkCreateRsp.Name

clear := Clear{
AuthHandle: AuthHandle{
Handle: tpm.RHLockout,
Auth: PasswordAuth(nil),
},
}
err = clear.Execute(thetpm)
if err != nil {
t.Fatalf("could not clear TPM: %v", err)
}

srkCreateRsp, err = srkCreate.Execute(thetpm)
if err != nil {
t.Fatalf("could not generate SRK: %v", err)
}
defer func() {
flush := FlushContext{
FlushHandle: srkCreateRsp.ObjectHandle,
}
err := flush.Execute(thetpm)
if err != nil {
t.Fatalf("could not flush SRK: %v", err)
}
}()

srkName2 := srkCreateRsp.Name

if bytes.Equal(srkName1.Buffer, srkName2.Buffer) {
t.Errorf("SRK Name did not change across clear, was %x both times", srkName1.Buffer)
}
}
Loading

0 comments on commit ece7af1

Please sign in to comment.