Skip to content

[Question] How to produce an audit log to remotely validate an audit session? #414

@loicsikidi

Description

@loicsikidi

Hi,

I'm currently working on audit session in order to achieve the following goals:

  1. remotely attest that a TPM really executed a sequence of commands w/ success
  2. (bonus) get the Response of each audited command

After reading a bunch of resources:

I've unsterstood the following: we have an untrusted component1 (outside the TPM) which maintain an audit log w/ TPM command & response parameters and TPM2_GetSessionAuditDigest allows to get an attestation about the digest of the audit session.

Theoretically, from the untrusted audit log a remote party is able to recompute a digest and check if it matches the one produced by TPM2_GetSessionAuditDigest to know if it can be trusted.

go-tpm/tpm2/audit.go

Lines 17 to 53 in bf12020

// NewAudit initializes a new CommandAudit with the specified hash algorithm.
func NewAudit(hash TPMIAlgHash) (*CommandAudit, error) {
h, err := hash.Hash()
if err != nil {
return nil, err
}
return &CommandAudit{
hash: hash,
digest: make([]byte, h.Size()),
}, nil
}
// AuditCommand extends the audit digest with the given command and response.
// Go Generics do not allow type parameters on methods, otherwise this would be
// a method on CommandAudit.
// See https://github.com/golang/go/issues/49085 for more information.
func AuditCommand[C Command[R, *R], R any](a *CommandAudit, cmd C, rsp *R) error {
cc := cmd.Command()
cpHash, err := auditCPHash[R](cc, a.hash, cmd)
if err != nil {
return err
}
rpHash, err := auditRPHash(cc, a.hash, rsp)
if err != nil {
return err
}
ha, err := a.hash.Hash()
if err != nil {
return err
}
h := ha.New()
h.Write(a.digest)
h.Write(cpHash)
h.Write(rpHash)
a.digest = h.Sum(nil)
return nil
}

CommandAudit & AuditCommand functions seems to provide this logic but not in a way that is suitable for my use case.

Ideally would like to obtain this kind of output:

hash(commandA)<DELIMITER>marshal(responseA)
hash(commandB)<DELIMITER>marshal(responseB)
hash(commandC)<DELIMITER>marshal(responseC)
...
  1. It would allow to keep command privacy2
  2. It would allow the remote party to unmarshal the response to access some values (e.g. GetCapability, etc.)
  3. It would allow to reproduce the hash w/ the same logic implemented in AuditCommand (i.e. auditRPHash)

It doesn't seems that Command or/and Response to be marshallable which prevent me to achieve my goals.

Does my request make sense or I miss something obvious?

Thank you in advance for your support!

Footnotes

  1. an application

  2. I would like to avoid to have access to auth value but maybe that even the marshal version is encrypted

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions