diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2017-01-05 03:46:21 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-01-05 03:46:21 +0000 |
commit | 6ece5a16ed875a5d8d5cb500844d43cae3c1413f (patch) | |
tree | 13b244e7dc09e4da773518847aede3b88228156e | |
parent | be42694d9f48772f52a9a03bd5a0a842e160fe1f (diff) | |
parent | 21756127fdebc0b0825aba875c7d0cc75057d3d8 (diff) | |
download | tpm2-6ece5a16ed875a5d8d5cb500844d43cae3c1413f.tar.gz |
serialize objects in NVMEMandroid-n-mr2-preview-1
am: 21756127fd
Change-Id: I3ec3888ba566dc15bd81084da00fe9e581e9296c
-rw-r--r-- | Implementation.h | 8 | ||||
-rw-r--r-- | NV.c | 162 | ||||
-rw-r--r-- | Object.c | 4 |
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 @@ -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; @@ -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; } // |