aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2017-01-05 03:46:21 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-01-05 03:46:21 +0000
commit6ece5a16ed875a5d8d5cb500844d43cae3c1413f (patch)
tree13b244e7dc09e4da773518847aede3b88228156e
parentbe42694d9f48772f52a9a03bd5a0a842e160fe1f (diff)
parent21756127fdebc0b0825aba875c7d0cc75057d3d8 (diff)
downloadtpm2-6ece5a16ed875a5d8d5cb500844d43cae3c1413f.tar.gz
serialize objects in NVMEMandroid-n-mr2-preview-1
am: 21756127fd Change-Id: I3ec3888ba566dc15bd81084da00fe9e581e9296c
-rw-r--r--Implementation.h8
-rw-r--r--NV.c162
-rw-r--r--Object.c4
3 files changed, 145 insertions, 29 deletions
diff --git a/Implementation.h b/Implementation.h
index 0d12c45..c7dc5c5 100644
--- a/Implementation.h
+++ b/Implementation.h
@@ -262,8 +262,12 @@
#define NV_MEMORY_SIZE 16076
// Versioning NV storage format will allow to smoothly migrate NVRAM contents.
// Versions:
-// 1 - full non-serialized objects in NVRAM, max SHA digest is SHA-256
-// 2 - full non-serialized objects in NVRAM, max SHA digest is SHA-512
+// 1 - full non-serialized objects in NVMEM, max SHA digest is SHA-256
+// 2 - a mix of serialized and non-serialized objects in NVMEM, max SHA digest
+// is SHA-512. Eviction objects can be stored either serialized or
+// non-serialized. The size of the stored entity smaller than
+// sizeof(OBJECT) is considered an indication of the serialized form.
+
#define NV_FORMAT_VERSION 2
#else
#define NV_MEMORY_SIZE 16384
diff --git a/NV.c b/NV.c
index f714c91..0099c19 100644
--- a/NV.c
+++ b/NV.c
@@ -1101,6 +1101,53 @@ NvIsUndefinedEvictHandle(
else
return FALSE;
}
+
+//
+//
+// NvUnmarshalObject()
+//
+// This function accepts a buffer containing a marshaled OBJECT
+// structure, a pointer to the area where the input data should be
+// unmarshaled, and a pointer to the size of the output area.
+//
+// No error checking is performed, unmarshaled data is guaranteed not to
+// spill over the allocated space.
+//
+static TPM_RC NvUnmarshalObject(OBJECT *o, BYTE **buf, INT32 *size)
+{
+ TPM_RC result;
+
+ // There is no generated function to unmarshal the attributes field, do it
+ // by hand.
+ MemoryCopy(&o->attributes, *buf, sizeof(o->attributes), *size);
+ *buf += sizeof(o->attributes);
+ *size -= sizeof(o->attributes);
+
+ result = TPMT_PUBLIC_Unmarshal(&o->publicArea, buf, size);
+ if (result != TPM_RC_SUCCESS)
+ return result;
+
+ result = TPMT_SENSITIVE_Unmarshal(&o->sensitive, buf, size);
+ if (result != TPM_RC_SUCCESS)
+ return result;
+
+#ifdef TPM_ALG_RSA
+ result = TPM2B_PUBLIC_KEY_RSA_Unmarshal(&o->privateExponent, buf, size);
+ if (result != TPM_RC_SUCCESS)
+ return result;
+#endif
+
+ result = TPM2B_NAME_Unmarshal(&o->qualifiedName, buf, size);
+ if (result != TPM_RC_SUCCESS)
+ return result;
+
+ result = TPMI_DH_OBJECT_Unmarshal(&o->evictHandle, buf, size, TRUE);
+ if (result != TPM_RC_SUCCESS)
+ return result;
+
+ return TPM2B_NAME_Unmarshal(&o->name, buf, size);
+}
+
//
//
// NvGetEvictObject()
@@ -1123,13 +1170,34 @@ NvGetEvictObject(
// Find the address of evict object
entityAddr = NvFindHandle(handle);
// If handle is not found, return an error
- if(entityAddr == 0)
+ if(entityAddr == 0) {
result = TPM_RC_HANDLE;
- else
- // Read evict object
- _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
- sizeof(OBJECT),
- object);
+ } else {
+ UINT32 storedSize;
+ UINT32 nextEntryAddr;
+
+ // Let's calculate the size of object as stored in NVMEM.
+ _plat__NvMemoryRead(entityAddr - sizeof(UINT32),
+ sizeof(UINT32), &nextEntryAddr);
+
+ storedSize = nextEntryAddr - entityAddr;
+
+ if (storedSize == (sizeof(TPM_HANDLE) + sizeof(OBJECT))) {
+ // Read evict object stored unmarshaled.
+ _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
+ sizeof(OBJECT),
+ object);
+ } else {
+ // Must be stored marshaled, let's unmarshal it.
+ BYTE marshaled[sizeof(OBJECT)];
+ INT32 max_size = sizeof(marshaled);
+ BYTE *marshaledPtr = marshaled;
+
+ _plat__NvMemoryRead(entityAddr + sizeof(TPM_HANDLE),
+ storedSize, marshaled);
+ result = NvUnmarshalObject(object, &marshaledPtr, &max_size);
+ }
+ }
// whether there is an error or not, make sure that the evict
// status of the object is set so that the slot will get freed on exit
object->attributes.evict = SET;
@@ -1494,6 +1562,51 @@ NvDefineIndex(
NvAddRAM(publicArea->nvIndex, publicArea->dataSize);
return TPM_RC_SUCCESS;
}
+
+//
+//
+// NvMarshalObject()
+//
+// This function marshals the passed in OBJECT structure into a buffer. A
+// pointer to pointer to the buffer and a pointer to the size of the
+// buffer are passed in for this function to update as appropriate.
+//
+// On top of marshaling the object, this function also modifies one of
+// the object's properties and sets the evictHandle field of the
+// marshaled object to the requested value.
+//
+// Returns
+//
+// Marshaled size of the object.
+//
+static UINT16 NvMarshalObject(OBJECT *o, TPMI_DH_OBJECT evictHandle,
+ BYTE **buf, INT32 *size)
+{
+ UINT16 marshaledSize;
+ OBJECT_ATTRIBUTES stored_attributes;
+
+ stored_attributes = o->attributes;
+ stored_attributes.evict = SET;
+ marshaledSize = sizeof(stored_attributes);
+ MemoryCopy(*buf, &stored_attributes, marshaledSize, *size);
+ *buf += marshaledSize;
+ *size -= marshaledSize;
+
+ marshaledSize += TPMT_PUBLIC_Marshal(&o->publicArea, buf, size);
+ marshaledSize += TPMT_SENSITIVE_Marshal(&o->sensitive, buf, size);
+#ifdef TPM_ALG_RSA
+ marshaledSize += TPM2B_PUBLIC_KEY_RSA_Marshal(&o->privateExponent,
+ buf, size);
+#endif
+ marshaledSize += TPM2B_NAME_Marshal(&o->qualifiedName, buf, size);
+
+ // Use the supplied handle instead of the object contents.
+ marshaledSize += TPMI_DH_OBJECT_Marshal(&evictHandle, buf, size);
+ marshaledSize += TPM2B_NAME_Marshal(&o->name, buf, size);
+
+ return marshaledSize;
+}
+
//
//
// NvAddEvictObject()
@@ -1514,35 +1627,34 @@ NvAddEvictObject(
{
// The buffer to be written to NV memory
BYTE nvBuffer[sizeof(TPM_HANDLE) + sizeof(OBJECT)];
- OBJECT *nvObject; // a pointer to the OBJECT data in
- // nvBuffer
UINT16 entrySize; // size of entry
+ BYTE *marshalSpace;
+ INT32 marshalRoom;
+
// evict handle type should match the object hierarchy
pAssert( ( NvIsPlatformPersistentHandle(evictHandle)
&& object->attributes.ppsHierarchy == SET)
|| ( NvIsOwnerPersistentHandle(evictHandle)
&& ( object->attributes.spsHierarchy == SET
|| object->attributes.epsHierarchy == SET)));
- // An evict needs 4 bytes of handle + sizeof OBJECT
- entrySize = sizeof(TPM_HANDLE) + sizeof(OBJECT);
- // Check if we have enough space to add the evict object
- // An evict object needs 8 bytes in index table + sizeof OBJECT
- // In this implementation, the only resource limitation is the available NV
- // space. Other implementation may have other limitation on evict object
- // handle space
- if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE;
- // Allocate a new evict handle
+
+ // Do not attemp storing a duplicate handle.
if(!NvIsUndefinedEvictHandle(evictHandle))
return TPM_RC_NV_DEFINED;
- // Copy evict object to nvBuffer
+
// Copy handle
- memcpy(nvBuffer, &evictHandle, sizeof(TPM_HANDLE));
- // Copy OBJECT
- nvObject = (OBJECT *) (nvBuffer + sizeof(TPM_HANDLE));
- *nvObject = *object;
- // Set evict attribute and handle
- nvObject->attributes.evict = SET;
- nvObject->evictHandle = evictHandle;
+ entrySize = sizeof(TPM_HANDLE);
+ memcpy(nvBuffer, &evictHandle, entrySize);
+
+ // Let's serialize the object before storing it in NVMEM
+ marshalSpace = nvBuffer + entrySize;
+ marshalRoom = sizeof(nvBuffer) - entrySize;
+ entrySize += NvMarshalObject(object, evictHandle,
+ &marshalSpace, &marshalRoom);
+
+ // Check if we have enough space to add this evict object
+ if(!NvTestSpace(entrySize, FALSE)) return TPM_RC_NV_SPACE;
+
// Add evict to NV memory
NvAdd(entrySize, entrySize, nvBuffer);
return TPM_RC_SUCCESS;
diff --git a/Object.c b/Object.c
index 06d717f..14ec018 100644
--- a/Object.c
+++ b/Object.c
@@ -268,8 +268,8 @@ ObjectAllocateSlot(
if(i == MAX_LOADED_OBJECTS) return FALSE;
*handle = i + TRANSIENT_FIRST;
*object = &s_objects[i].object.entity;
- // Initialize the object attributes
- MemorySet(&((*object)->attributes), 0, sizeof(OBJECT_ATTRIBUTES));
+ // Initialize the container.
+ MemorySet(*object, 0, sizeof(**object));
return TRUE;
}
//