diff --git a/linux/device.go b/linux/device.go index 4981438..da74d70 100644 --- a/linux/device.go +++ b/linux/device.go @@ -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 @@ -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() @@ -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. diff --git a/linux/transport.go b/linux/transport.go index 120c010..3afb965 100644 --- a/linux/transport.go +++ b/linux/transport.go @@ -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)