Repository: google/go-tpm
Pull request #176 (2020-06-12 07:38:09)

TPM12: Fix nvReadValue 
now works with no authentication
fix GetNVIndex, GetNVList
rename TestNVReadValue to TestNVReadValueNoAuth


Patch:
diff --git a/tpm/commands.go b/tpm/commands.go
index 9b517b3..7af3685 100644
--- a/tpm/commands.go
+++ b/tpm/commands.go
@@ -175,17 +175,24 @@ func nvDefineSpace(rw io.ReadWriter, nvData NVDataPublic, enc digest, ca *comman
 }
 
 // nvReadValue reads from the NVRAM
-// If TPM isn't locked, no authentification is needed.
+// If TPM isn't locked, and for some nv permission no authentification is needed.
 // See TPM-Main-Part-3-Commands-20.4
 func nvReadValue(rw io.ReadWriter, index, offset, len uint32, ca *commandAuth) ([]byte, *responseAuth, uint32, error) {
 	var b tpmutil.U32Bytes
 	var ra responseAuth
+	var ret uint32
+	var err error
 	in := []interface{}{index, offset, len}
+	out := []interface{}{&b}
+	// Auth is needed
 	if ca != nil {
 		in = append(in, ca)
+		out = append(out, ra)
+		ret, err = submitTPMRequest(rw, tagRQUAuth1Command, ordNVReadValue, in, out)
+	} else {
+		// Auth is not needed
+		ret, err = submitTPMRequest(rw, tagRQUCommand, ordNVReadValue, in, out)
 	}
-	out := []interface{}{&b, &ra}
-	ret, err := submitTPMRequest(rw, tagRQUAuth1Command, ordNVReadValue, in, out)
 	if err != nil {
 		return nil, nil, 0, err
 	}
diff --git a/tpm/tpm.go b/tpm/tpm.go
index 0a558fa..d3afab5 100644
--- a/tpm/tpm.go
+++ b/tpm/tpm.go
@@ -1152,31 +1152,28 @@ func GetAlgs(rw io.ReadWriter) ([]Algorithm, error) {
 // GetNVList returns a list of TPM_NV_INDEX values that
 // are currently allocated NV storage through TPM_NV_DefineSpace.
 func GetNVList(rw io.ReadWriter) ([]uint32, error) {
-	var nvList []uint32
 	buf, err := getCapability(rw, capNVList, 0)
 	if err != nil {
 		return nil, err
 	}
-	r := bytes.NewReader(buf)
-	err = binary.Read(r, binary.LittleEndian, &nvList)
+	nvList := make([]uint32, len(buf)/4)
+	for i := range nvList {
+		nvList[i] = uint32(binary.BigEndian.Uint32(buf[i*4 : (i+1)*4]))
+	}
+
 	return nvList, err
 }
 
 // GetNVIndex returns the structure of NVDataPublic which contains
 // information about the requested NV Index.
 // See: TPM-Main-Part-2-TPM-Structures_v1.2_rev116_01032011, P.167
-func GetNVIndex(rw io.ReadWriter, nvIndex uint32) (NVDataPublic, error) {
+func GetNVIndex(rw io.ReadWriter, nvIndex uint32) (*NVDataPublic, error) {
 	var nvInfo NVDataPublic
-	buf, err := getCapability(rw, capNVIndex, 0)
-	if err != nil {
-		return nvInfo, fmt.Errorf("failed to get capability NVIndex: %v", err)
-	}
-	r := bytes.NewReader(buf)
-	err = binary.Read(r, binary.LittleEndian, &nvInfo)
-	if err != nil {
-		return nvInfo, fmt.Errorf("failed to read nvInfo: %v", err)
+	buf, _ := getCapability(rw, capNVIndex, nvIndex)
+	if _, err := tpmutil.Unpack(buf, &nvInfo); err != nil {
+		return &nvInfo, err
 	}
-	return nvInfo, nil
+	return &nvInfo, nil
 }
 
 // GetCapabilityRaw reads the requested capability and sub-capability from the


Test patch:
diff --git a/tpm/tpm_test.go b/tpm/tpm_test.go
index 7cdbd38..bf8401d 100644
--- a/tpm/tpm_test.go
+++ b/tpm/tpm_test.go
@@ -117,7 +117,7 @@ func TestGetNVIndex(t *testing.T) {
 		if err != nil {
 			t.Fatalf("Can't read NVDataPublic of index: %v with: %v", nvEntry, err)
 		}
-		nvInfo = append(nvInfo, index)
+		nvInfo = append(nvInfo, *index)
 	}
 	t.Logf("NVIndices with Attributes:%v", nvInfo)
 }
@@ -665,25 +665,26 @@ func TestNVWriteValue(t *testing.T) {
 
 }
 
-func TestNVReadValue(t *testing.T) {
-	ownAuth := getAuth("TPM_OWNER_AUTH")
+func TestNVReadValueNoAuth(t *testing.T) {
 	rwc := openTPMOrSkip(t)
 	defer rwc.Close()
 	//Get NVList
 	nvList, err := GetNVList(rwc)
 	if err != nil {
-		t.Fatalf("no values to read in nvram")
+		t.Fatalf("error reading nvlist: %v", err)
 	}
-
 	for _, item := range nvList {
 		pubData, err := GetNVIndex(rwc, item)
 		if err != nil {
 			t.Errorf("reading index: %v has no data: %v", item, err)
 		}
-		indexvalue, err := NVReadValue(rwc, pubData.NVIndex, 0, pubData.Size, ownAuth[:])
+		indexvalue, err := NVReadValue(rwc, pubData.NVIndex, 0, pubData.Size, nil)
 		if err != nil {
 			t.Logf("cant read index: %v", err)
 		}
 		t.Logf("indexvalue: %v", indexvalue)
 	}
+	if len(nvList) == 0 {
+		t.Logf("no values to read in nvram")
+	}
 }