Skip to content

Commit

Permalink
linux: use the actual maximum response side in non partial read mode
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisccoulson committed Jan 12, 2024
1 parent f19ff6e commit d499036
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 44 deletions.
123 changes: 80 additions & 43 deletions linux/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,44 +59,6 @@ func (r *nonBlockingTpmFileReader) Read(data []byte) (int, error) {
return n, err
}

func isPartialReadSupported(path string) bool {
f, err := os.OpenFile(path, os.O_RDWR, 0)
if err != nil {
return false
}

tf := &tpmFile{file: f}
defer tf.Close()

cmd := tpm2.MustMarshalCommandPacket(
tpm2.CommandGetCapability, nil, nil,
mu.MustMarshalToBytes(tpm2.CapabilityTPMProperties, tpm2.PropertyManufacturer, uint32(1)),
)
if _, err := tf.Write(cmd); err != nil {
return false
}

var rspHdr tpm2.ResponseHeader
buf := make([]byte, binary.Size(rspHdr))
if _, err := io.ReadFull(tf, buf); err != nil {
return false
}
if _, err := mu.UnmarshalFromBytes(buf, &rspHdr); err != nil {
return false
}
if rspHdr.ResponseCode != tpm2.ResponseSuccess {
return false
}

var moreData bool
var capabilityData *tpm2.CapabilityData
if _, err := mu.UnmarshalFromReader(&nonBlockingTpmFileReader{tf}, &moreData, &capabilityData); err != nil {
return false
}

return true
}

type tpmDevices struct {
once sync.Once
devices []*RawDevice
Expand Down Expand Up @@ -129,16 +91,86 @@ type Device struct {
sysfsPath string
version TPMMajorVersion

partialReadSupportOnce sync.Once
partialReadSupported bool
prsOnce sync.Once
partialReadSupported bool

mrsOnce sync.Once
mrs uint32
}

func (d *Device) checkPartialReadSupport() {
d.partialReadSupportOnce.Do(func() {
d.partialReadSupported = isPartialReadSupported(d.path)
d.prsOnce.Do(func() {
d.partialReadSupported = func() bool {
f, err := os.OpenFile(d.path, os.O_RDWR, 0)
if err != nil {
return false
}

tf := &tpmFile{file: f}
defer tf.Close()

cmd := tpm2.MustMarshalCommandPacket(
tpm2.CommandGetCapability, nil, nil,
mu.MustMarshalToBytes(tpm2.CapabilityTPMProperties, tpm2.PropertyManufacturer, uint32(1)),
)
if _, err := tf.Write(cmd); err != nil {
return false
}

var rspHdr tpm2.ResponseHeader
buf := make([]byte, binary.Size(rspHdr))
if _, err := io.ReadFull(tf, buf); err != nil {
return false
}
if _, err := mu.UnmarshalFromBytes(buf, &rspHdr); err != nil {
return false
}
if rspHdr.ResponseCode != tpm2.ResponseSuccess {
return false
}

var moreData bool
var capabilityData *tpm2.CapabilityData
if _, err := mu.UnmarshalFromReader(&nonBlockingTpmFileReader{tf}, &moreData, &capabilityData); err != nil {
return false
}

return true
}()
})
}

type dummyDevice struct {
d *Device
f *os.File
}

func (d *dummyDevice) Open() (tpm2.Transport, error) {
return newTransport(&tpmFile{file: d.f}, false, maxResponseSize), nil
}

func (d *dummyDevice) String() string {
return d.d.String()
}

func (d *Device) maxResponseSize(f *os.File) uint32 {
d.mrsOnce.Do(func() {
d.mrs = func() uint32 {
tpm, err := tpm2.OpenTPMDevice(&dummyDevice{d: d, f: f})
if err != nil {
return maxResponseSize
}

sz, err := tpm.GetCapabilityTPMProperty(tpm2.PropertyMaxResponseSize)
if err != nil {
return maxResponseSize
}
return sz
}()
})
return d.mrs
}

func (d *Device) openInternal() (*Transport, error) {
d.checkPartialReadSupport()

Expand All @@ -147,7 +179,12 @@ func (d *Device) openInternal() (*Transport, error) {
return nil, err
}

return newTransport(&tpmFile{file: f}, d.partialReadSupported), nil
var mrs uint32
if !d.partialReadSupported {
mrs = d.maxResponseSize(f)
}

return newTransport(&tpmFile{file: f}, d.partialReadSupported, mrs), nil
}

// Path returns the path of the character device.
Expand Down
2 changes: 1 addition & 1 deletion linux/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type Transport struct {
statter fileStatter
}

func newTransport(file *tpmFile, partialReadSupported bool) *Transport {
func newTransport(file *tpmFile, partialReadSupported bool, maxResponseSize uint32) *Transport {
var r io.Reader = file
if !partialReadSupported {
r = transportutil.BufferResponses(r, maxResponseSize)
Expand Down

0 comments on commit d499036

Please sign in to comment.