Added TPM command to read space permissions, and a correctness test.

Review URL: http://codereview.chromium.org/2719006
diff --git a/src/testsuite/Makefile b/src/testsuite/Makefile
index e63b61b..da0c258 100644
--- a/src/testsuite/Makefile
+++ b/src/testsuite/Makefile
@@ -34,6 +34,7 @@
         tpmtest_lock \
         tpmtest_readonly \
         tpmtest_redefine \
+        tpmtest_spaceperm \
         tpmtest_writelimit \
 
 all: $(TESTS)
diff --git a/src/testsuite/spaceperm.c b/src/testsuite/spaceperm.c
new file mode 100644
index 0000000..38a68cd
--- /dev/null
+++ b/src/testsuite/spaceperm.c
@@ -0,0 +1,47 @@
+/* Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* Test of space permissions retrieval.  The spaces 0xcafe and 0xcaff must have
+ * already been defined (by running, for instance, the "redefine" test).
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <tss/tcs.h>
+
+#include "tlcl.h"
+
+#define INDEX0 0xcafe
+#define INDEX1 0xcaff
+
+int main(int argc, char** argv) {
+  uint32_t perm;
+  uint32_t perm_pp_gl = TPM_NV_PER_PPWRITE | TPM_NV_PER_GLOBALLOCK;
+  uint32_t perm_pp = TPM_NV_PER_PPWRITE;
+  uint32_t result;
+
+  TlclLibInit();
+
+#if !USE_TPM_EMULATOR
+  TlclStartup();
+  TlclContinueSelfTest();
+#endif
+
+  TlclAssertPhysicalPresence();
+
+  result = TlclGetPermissions(INDEX0, &perm);
+  assert(result == TPM_SUCCESS);
+  printf("permissions for INDEX0 = 0x%x\n", perm);
+  assert((perm & perm_pp_gl) == perm_pp_gl);
+
+  result = TlclGetPermissions(INDEX1, &perm);
+  assert(result == TPM_SUCCESS);
+  printf("permissions for INDEX1 = 0x%x\n", perm);
+  assert((perm & perm_pp) == perm_pp);
+
+  printf("Test completed successfully\n");
+  exit(0);
+}
diff --git a/src/tlcl/generator.c b/src/tlcl/generator.c
index 4a9e89d..f5ad7ad 100644
--- a/src/tlcl/generator.c
+++ b/src/tlcl/generator.c
@@ -252,14 +252,14 @@
   return cmd;  
 }
 
-Command* BuildGetCapabilityCommand(void) {
+Command* BuildGetFlagsCommand(void) {
   int size = (kTpmRequestHeaderLength +
               sizeof(TPM_CAPABILITY_AREA) +   /* capArea */
               sizeof(uint32_t) +              /* subCapSize */
-              sizeof(uint32_t));               /* subCap */
+              sizeof(uint32_t));              /* subCap */
     
   Command* cmd = newCommand(TPM_ORD_GetCapability, size);
-  cmd->name = "tpm_getcapability_cmd";
+  cmd->name = "tpm_getflags_cmd";
   AddInitializedField(cmd, kTpmRequestHeaderLength,
                       sizeof(TPM_CAPABILITY_AREA), TPM_CAP_FLAG);
   AddInitializedField(cmd, kTpmRequestHeaderLength +
@@ -271,6 +271,24 @@
   return cmd;  
 }
 
+Command* BuildGetPermissionsCommand(void) {
+  int size = (kTpmRequestHeaderLength +
+              sizeof(TPM_CAPABILITY_AREA) +   /* capArea */
+              sizeof(uint32_t) +              /* subCapSize */
+              sizeof(uint32_t));              /* subCap */
+    
+  Command* cmd = newCommand(TPM_ORD_GetCapability, size);
+  cmd->name = "tpm_getpermissions_cmd";
+  AddInitializedField(cmd, kTpmRequestHeaderLength,
+                      sizeof(TPM_CAPABILITY_AREA), TPM_CAP_NV_INDEX);
+  AddInitializedField(cmd, kTpmRequestHeaderLength +
+                      sizeof(TPM_CAPABILITY_AREA),
+                      sizeof(uint32_t), sizeof(uint32_t));
+  AddVisibleField(cmd, "index", kTpmRequestHeaderLength +
+                  sizeof(TPM_CAPABILITY_AREA) + sizeof(uint32_t));
+  return cmd;  
+}
+
 /* Output the fields of a structure.
  */
 void OutputFields(Field* fld) {
@@ -379,7 +397,8 @@
   BuildForceClearCommand,
   BuildPhysicalEnableCommand,
   BuildPhysicalSetDeactivatedCommand,
-  BuildGetCapabilityCommand,
+  BuildGetFlagsCommand,
+  BuildGetPermissionsCommand,
   BuildExtendCommand,
 };
 
@@ -412,6 +431,10 @@
   printf("/* This file is automatically generated */\n\n");
   OutputCommands(commands);
   printf("const int kWriteInfoLength = %d;\n", (int) sizeof(TPM_WRITE_INFO));
+  printf("const int kNvDataPublicPermissionsOffset = %d;\n",
+         (int) (offsetof(TPM_NV_DATA_PUBLIC, permission) +
+                2 * PCR_SELECTION_FIX +
+                offsetof(TPM_NV_ATTRIBUTES, attributes)));
 
   FreeCommands(commands);
   return 0;
diff --git a/src/tlcl/tlcl.c b/src/tlcl/tlcl.c
index 524cf2e..4ef5e40 100644
--- a/src/tlcl/tlcl.c
+++ b/src/tlcl/tlcl.c
@@ -350,7 +350,7 @@
   uint32_t result;
   uint32_t size;
 
-  SendReceive(tpm_getcapability_cmd.buffer, response, sizeof(response));
+  SendReceive(tpm_getflags_cmd.buffer, response, sizeof(response));
   result = TpmReturnCode(response);
   if (result != TPM_SUCCESS) {
     return result;
@@ -377,3 +377,20 @@
   memcpy(out_digest, response + kTpmResponseHeaderLength, kPcrDigestLength);
   return TpmReturnCode(response);
 }
+
+uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions) {
+  uint8_t response[TPM_LARGE_ENOUGH_COMMAND_SIZE];
+  uint8_t* nvdata;
+  uint32_t result;
+  uint32_t size;
+
+  ToTpmUint32(tpm_getpermissions_cmd.index, index);
+  SendReceive(tpm_getpermissions_cmd.buffer, response, sizeof(response));
+  result = TpmReturnCode(response);
+  if (result != TPM_SUCCESS) {
+    return result;
+  }
+  nvdata = response + kTpmResponseHeaderLength + sizeof(size);
+  FromTpmUint32(nvdata + kNvDataPublicPermissionsOffset, permissions);
+  return result;
+}
diff --git a/src/tlcl/tlcl.h b/src/tlcl/tlcl.h
index 6bbec5c..e170cb8 100644
--- a/src/tlcl/tlcl.h
+++ b/src/tlcl/tlcl.h
@@ -149,4 +149,8 @@
  */
 uint32_t TlclExtend(int pcr_num, uint8_t* in_digest, uint8_t* out_digest);
 
+/* Gets the permission bits for the NVRAM space with |index|.
+ */
+uint32_t TlclGetPermissions(uint32_t index, uint32_t* permissions);
+
 #endif  /* TPM_LITE_TLCL_H_ */