Skip to content

Commit

Permalink
Implemented and tested TPM2_Certify.
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew Tsai committed Jul 12, 2022
1 parent d20ef6e commit 9d0b8e9
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 0 deletions.
147 changes: 147 additions & 0 deletions direct/tpm2/certify_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package tpm2

import (
"crypto"
"crypto/rsa"
"crypto/sha256"
"testing"

"github.com/google/go-tpm/direct/helpers"
"github.com/google/go-tpm/direct/structures/tpm"
"github.com/google/go-tpm/direct/structures/tpm2b"
"github.com/google/go-tpm/direct/structures/tpma"
"github.com/google/go-tpm/direct/structures/tpml"
"github.com/google/go-tpm/direct/structures/tpms"
"github.com/google/go-tpm/direct/structures/tpmt"
"github.com/google/go-tpm/direct/structures/tpmu"
"github.com/google/go-tpm/direct/transport/simulator"
)

func TestCertify(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")

PCR7, err := CreatePCRSelection([]int{7})
if err != nil {
t.Fatalf("Failed to create PCRSelection")
}
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,
},
},
},
}

pcrSelection := tpml.PCRSelection{
PCRSelections: []tpms.PCRSelection{
{
Hash: tpm.AlgSHA256,
PCRSelect: PCR7,
},
},
}

createPrimarySigner := CreatePrimary{
PrimaryHandle: tpm.RHOwner,
InSensitive: tpm2b.SensitiveCreate{
Sensitive: tpms.SensitiveCreate{
UserAuth: tpm2b.Auth{
Buffer: Auth,
},
},
},
InPublic: public,
CreationPCR: pcrSelection,
}
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)

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

certify := Certify{
ObjectHandle: AuthHandle{
Handle: rspSubject.ObjectHandle,
Name: rspSubject.Name,
Auth: PasswordAuth(Auth),
},
SignHandle: AuthHandle{
Handle: rspSigner.ObjectHandle,
Name: rspSigner.Name,
Auth: PasswordAuth(Auth),
},
QualifyingData: tpm2b.Data{
Buffer: nil,
},
InScheme: tpmt.SigScheme{
Scheme: tpm.AlgNull,
},
}

rspCert, err := certify.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 retrive 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)
}
}
36 changes: 36 additions & 0 deletions direct/tpm2/tpm2.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,42 @@ type SequenceCompleteResponse struct {
// Response implements the Response interface.
func (*SequenceCompleteResponse) Response() tpm.CC { return tpm.CCSequenceComplete }

// Certify is the input to TPM2_Certify.
// See definition in Part 3, Commands, section 18.2.
type Certify struct {
// handle of the object to be certified, Auth Index: 1, Auth Role: ADMIN
ObjectHandle handle `gotpm:"handle,auth"`
// handle of the key used to sign the attestation structure, Auth Index: 2, Auth Role: USER
SignHandle handle `gotpm:"handle,auth"`
// user provided qualifying data
QualifyingData tpm2b.Data
// signing scheme to use if the scheme for signHandle is TPM_ALG_NULL
InScheme tpmt.SigScheme
}

// Command implements the Command interface.
func (*Certify) Command() tpm.CC { return tpm.CCCertify }

// Execute executes the command and returns the response.
func (cmd *Certify) Execute(t transport.TPM, s ...Session) (*CertifyResponse, error) {
var rsp CertifyResponse
if err := execute(t, cmd, &rsp, s...); err != nil {
return nil, err
}
return &rsp, nil
}

// CertifyResponse is the response from TPM2_Certify.
type CertifyResponse struct {
// the structure that was signed
CertifyInfo tpm2b.Attest
// the asymmetric signature over certifyInfo using the key referenced by signHandle
Signature tpmt.Signature
}

// Response implements the Response interface.
func (*CertifyResponse) Response() tpm.CC { return tpm.CCCertify }

// Quote is the input to TPM2_Quote.
// See definition in Part 3, Commands, section 18.4
type Quote struct {
Expand Down

0 comments on commit 9d0b8e9

Please sign in to comment.