/
tpm.go
179 lines (143 loc) · 7.14 KB
/
tpm.go
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Copyright 2023 Canonical Ltd.
// Licensed under the LGPLv3 with static-linking exception.
// See LICENCE file for details.
package policyutil
import (
"errors"
"github.com/canonical/go-tpm2"
)
// TPMHelper provides a way for [Policy.Execute] to communicate with a TPM.
type TPMHelper interface {
// StartAuthSession returns an authorization session with the specified type and
// algorithm. It is required for any policy that includes TPM2_PolicySecret or
// TPM2_PolicyNV assertions.
StartAuthSession(sessionType tpm2.SessionType, alg tpm2.HashAlgorithmId) (SessionContext, PolicySession, error)
// LoadExternal loads the supplied external object into the TPM. It is required by
// any policy that includes TPM2_PolicySigned or TPM2_PolicyAuthorize assertions.
LoadExternal(inPrivate *tpm2.Sensitive, inPublic *tpm2.Public, hierarchy tpm2.Handle) (ResourceContext, error)
// ReadPublic returns the public area of the resource at the specified handle. It
// is required by any policy that includes TPM2_PolicySecret assertions on persistent or
// transient objects.
ReadPublic(handle tpm2.HandleContext) (*tpm2.Public, error)
// VerifySignature verifies the supplied signature with the supplied key object. It
// is required by any policy that includes TPM2_PolicyAuthorize assertions.
VerifySignature(key tpm2.ResourceContext, digest tpm2.Digest, signature *tpm2.Signature) (*tpm2.TkVerified, error)
// PCRRead returns the PCR values for the specified selection. It is required to
// automatically resolve branches where branches include TPM2_PolicyPCR assertions.
PCRRead(pcrs tpm2.PCRSelectionList) (tpm2.PCRValues, error)
// ReadClock returns the current time info. It is required to automatically resolve
// branches where branches include TPM2_PolicyCounterTimer assertions.
ReadClock() (*tpm2.TimeInfo, error)
// NVRead returns the contents of the specified NV index. It is required to automatically
// resolve branches where branches include TPM2_PolicyNV assertions. This will only
// be called if the index has an authorization policy with a branch that includes
// TPM2_PolicyCommandCode for TPM2_NV_Read and no other assertions.
NVRead(auth, index tpm2.ResourceContext, size, offset uint16, authAuthSession tpm2.SessionContext) (tpm2.MaxNVBuffer, error)
// NVReadPublic returns the public area of the NV index at the specified handle. It
// is required by any policy that includes TPM2_PolicyNV assertions or TPM2_PolicySecret
// assertions on NV indices.
NVReadPublic(handle tpm2.HandleContext) (*tpm2.NVPublic, error)
// GetPermanentHandleAuthPolicy returns the auth policy digest for the specified
// permanent handle, if there is one. If there isn't one, it returns a null hash.
GetPermanentHandleAuthPolicy(handle tpm2.Handle) (tpm2.TaggedHash, error)
}
type onlineTpmHelper struct {
newPolicySession NewPolicySessionFn
tpm *tpm2.TPMContext
sessions []tpm2.SessionContext
}
// TPMHelperParams provides parameters to [NewTPMHelper].
type TPMHelperParams struct {
// NewPolicySessionFn allows the function used to create a new PolicySession
// in StartAuthSession to be overridden. The default is NewTPMPolicySession.
NewPolicySessionFn NewPolicySessionFn
}
// NewTPMHelper returns an implementation of TPMHelper that uses the supplied TPM context.
func NewTPMHelper(tpm *tpm2.TPMContext, params *TPMHelperParams, sessions ...tpm2.SessionContext) TPMHelper {
if params == nil {
params = new(TPMHelperParams)
}
newPolicySession := params.NewPolicySessionFn
if newPolicySession == nil {
newPolicySession = NewTPMPolicySession
}
return &onlineTpmHelper{
newPolicySession: newPolicySession,
tpm: tpm,
sessions: sessions,
}
}
func (h *onlineTpmHelper) StartAuthSession(sessionType tpm2.SessionType, alg tpm2.HashAlgorithmId) (SessionContext, PolicySession, error) {
session, err := h.tpm.StartAuthSession(nil, nil, sessionType, nil, alg, h.sessions...)
if err != nil {
return nil, nil, err
}
switch sessionType {
case tpm2.SessionTypeHMAC:
return newTpmSessionContext(h.tpm, session), nil, nil
case tpm2.SessionTypePolicy:
policySession := h.newPolicySession(h.tpm, session, h.sessions...)
return policySession.Context(), policySession, nil
default:
panic("not reached")
}
}
func (h *onlineTpmHelper) LoadExternal(inPrivate *tpm2.Sensitive, inPublic *tpm2.Public, hierarchy tpm2.Handle) (ResourceContext, error) {
rc, err := h.tpm.LoadExternal(inPrivate, inPublic, hierarchy, h.sessions...)
if err != nil {
return nil, err
}
return newTpmResourceContextFlushable(h.tpm, rc, nil), nil
}
func (h *onlineTpmHelper) ReadPublic(handle tpm2.HandleContext) (*tpm2.Public, error) {
pub, _, _, err := h.tpm.ReadPublic(handle, h.sessions...)
return pub, err
}
func (h *onlineTpmHelper) VerifySignature(key tpm2.ResourceContext, digest tpm2.Digest, signature *tpm2.Signature) (*tpm2.TkVerified, error) {
return h.tpm.VerifySignature(key, digest, signature, h.sessions...)
}
func (h *onlineTpmHelper) PCRRead(pcrs tpm2.PCRSelectionList) (tpm2.PCRValues, error) {
_, values, err := h.tpm.PCRRead(pcrs, h.sessions...)
return values, err
}
func (h *onlineTpmHelper) ReadClock() (*tpm2.TimeInfo, error) {
return h.tpm.ReadClock(h.sessions...)
}
func (h *onlineTpmHelper) NVRead(auth, index tpm2.ResourceContext, size, offset uint16, authAuthSession tpm2.SessionContext) (tpm2.MaxNVBuffer, error) {
return h.tpm.NVReadRaw(auth, index, size, offset, authAuthSession, h.sessions...)
}
func (h *onlineTpmHelper) NVReadPublic(handle tpm2.HandleContext) (*tpm2.NVPublic, error) {
pub, _, err := h.tpm.NVReadPublic(handle, h.sessions...)
return pub, err
}
func (h *onlineTpmHelper) GetPermanentHandleAuthPolicy(handle tpm2.Handle) (tpm2.TaggedHash, error) {
return h.tpm.GetCapabilityAuthPolicy(handle, h.sessions...)
}
type nullTpmHelper struct{}
func (*nullTpmHelper) StartAuthSession(sessionType tpm2.SessionType, alg tpm2.HashAlgorithmId) (SessionContext, PolicySession, error) {
return nil, nil, errors.New("no TPMHelper")
}
func (*nullTpmHelper) LoadExternal(inPrivate *tpm2.Sensitive, inPublic *tpm2.Public, hierarchy tpm2.Handle) (ResourceContext, error) {
return nil, errors.New("no TPMHelper")
}
func (*nullTpmHelper) ReadPublic(handle tpm2.HandleContext) (*tpm2.Public, error) {
return nil, errors.New("no TPMHelper")
}
func (*nullTpmHelper) VerifySignature(key tpm2.ResourceContext, digest tpm2.Digest, signature *tpm2.Signature) (*tpm2.TkVerified, error) {
return nil, errors.New("no TPMHelper")
}
func (*nullTpmHelper) PCRRead(pcrs tpm2.PCRSelectionList) (tpm2.PCRValues, error) {
return nil, errors.New("no TPMHelper")
}
func (*nullTpmHelper) ReadClock() (*tpm2.TimeInfo, error) {
return nil, errors.New("no TPMHelper")
}
func (*nullTpmHelper) NVRead(auth, index tpm2.ResourceContext, size, offset uint16, authAuthSession tpm2.SessionContext) (tpm2.MaxNVBuffer, error) {
return nil, errors.New("no TPMHelper")
}
func (*nullTpmHelper) NVReadPublic(handle tpm2.HandleContext) (*tpm2.NVPublic, error) {
return nil, errors.New("no TPMHelper")
}
func (*nullTpmHelper) GetPermanentHandleAuthPolicy(handle tpm2.Handle) (tpm2.TaggedHash, error) {
return tpm2.MakeTaggedHash(tpm2.HashAlgorithmNull, nil), errors.New("no TPMHelper")
}