1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
|
package tpm2
import (
"bytes"
"crypto"
"reflect"
)
// PolicyCalculator represents a TPM 2.0 policy that needs to be calculated
// synthetically (i.e., without a TPM).
type PolicyCalculator struct {
alg TPMIAlgHash
hash crypto.Hash
state []byte
}
// NewPolicyCalculator creates a fresh policy using the given hash algorithm.
func NewPolicyCalculator(alg TPMIAlgHash) (*PolicyCalculator, error) {
hash, err := alg.Hash()
if err != nil {
return nil, err
}
return &PolicyCalculator{
alg: alg,
hash: hash,
state: make([]byte, hash.Size()),
}, nil
}
// Reset resets the internal state of the policy hash to all 0x00.
func (p *PolicyCalculator) Reset() {
p.state = make([]byte, p.hash.Size())
}
// Update updates the internal state of the policy hash by appending the
// current state with the given contents, and updating the new state to the
// hash of that.
func (p *PolicyCalculator) Update(data ...interface{}) error {
hash := p.hash.New()
hash.Write(p.state)
var buf bytes.Buffer
for _, d := range data {
if err := marshal(&buf, reflect.ValueOf(d)); err != nil {
return err
}
}
hash.Write(buf.Bytes())
p.state = hash.Sum(nil)
return nil
}
// Hash returns the current state of the policy hash.
func (p *PolicyCalculator) Hash() *TPMTHA {
result := TPMTHA{
HashAlg: p.alg,
Digest: make([]byte, len(p.state)),
}
copy(result.Digest, p.state)
return &result
}
|