Make NVRAM and Keygen examples store the encoded public key part to save space

Before examples were always storing the maximum public key part size,
using sizeof(TPM2B_PUBLIC), with many empty fields. This meant, always
storing 616 bytes of public part, even if the public key part was less.

* writekeyBlob/readKeyBlob use the actual size of public key part
* NVRAM store/read use the actual size of the public key part
* Minor fixes from peer review
* Added comment to nvram/store about Host Endianness, per peer review
* Added public API for appending/parsing TPM2B_PUBLIC to byte streams

Signed-off-by: Dimitar Tomov <dimi@wolfssl.com>
pull/143/head
Dimitar Tomov 2021-03-11 14:08:30 +02:00 committed by David Garske
parent 56db5fe67c
commit f0540d688e
6 changed files with 144 additions and 20 deletions

View File

@ -70,7 +70,7 @@ static void usage(void)
static int symChoice(const char* arg, TPM_ALG_ID* algSym, int* keyBits,
char* symMode)
{
unsigned long len = XSTRLEN(arg);
size_t len = XSTRLEN(arg);
if (len != SYM_EXTRA_OPTS_LEN) {
return TPM_RC_FAILURE;
@ -96,7 +96,7 @@ static int symChoice(const char* arg, TPM_ALG_ID* algSym, int* keyBits,
}
*keyBits = atoi(&arg[SYM_EXTRA_OPTS_KEY_BITS_POS]);
if(*keyBits != 128 && *keyBits != 256) {
if(*keyBits != 128 && *keyBits != 192 && *keyBits != 256) {
return TPM_RC_FAILURE;
}
@ -119,7 +119,7 @@ int TPM2_Keygen_Example(void* userCtx, int argc, char *argv[])
int bAIK = 1;
int keyBits = 256;
const char* outputFile = "keyblob.bin";
unsigned long len = 0;
size_t len = 0;
char symMode[] = "aesctr";
if (argc >= 2) {

View File

@ -67,6 +67,9 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[])
int paramEncAlg = TPM_ALG_NULL;
int partialRead = 0;
int offset = 0;
/* Needed for TPM2_ParsePublic */
byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
int pubAreaSize;
if (argc >= 2) {
if (XSTRNCMP(argv[1], "-?", 2) == 0 ||
@ -137,16 +140,32 @@ int TPM2_NVRAM_Read_Example(void* userCtx, int argc, char *argv[])
XMEMCPY(nv.handle.auth.buffer, auth.buffer, auth.size);
if (partialRead != PRIVATE_PART_ONLY) {
readSize = sizeof(keyBlob.pub);
printf("Trying to read %d bytes of public key part from NV\n", readSize);
readSize = sizeof(keyBlob.pub.size);
printf("Trying to read %d bytes of public key size marker\n", readSize);
rc = wolfTPM2_NVReadAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_INDEX,
(byte*)&keyBlob.pub, &readSize, 0);
(byte*)&keyBlob.pub.size, &readSize, 0);
if (rc != 0) {
printf("Was a public key part written? (see nvram/store)\n");
goto exit;
}
printf("Successfully read public key part from NV\n\n");
offset = readSize;
offset += readSize;
readSize = sizeof(UINT16) + keyBlob.pub.size; /* account for TPM2B size marker */
printf("Trying to read %d bytes of public key part from NV\n", keyBlob.pub.size);
rc = wolfTPM2_NVReadAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_INDEX,
pubAreaBuffer, &readSize, offset);
if (rc != 0) goto exit;
printf("Successfully read public key part from NV\n\n");
offset += readSize;
/* Necessary for storing the publicArea with the correct encoding */
rc = TPM2_ParsePublic(&keyBlob.pub, pubAreaBuffer, sizeof(pubAreaBuffer), &pubAreaSize);
if (rc != TPM_RC_SUCCESS) {
printf("Decoding of PublicArea failed. Unable to extract correctly.\n");
goto exit;
}
#ifdef WOLFTPM_DEBUG_VERBOSE
TPM2_PrintPublicArea(&keyBlob.pub);
printf("\n");

View File

@ -68,6 +68,9 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[])
int paramEncAlg = TPM_ALG_NULL;
int partialStore = 0;
int offset = 0;
/* Needed for TPM2_AppendPublic */
byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
int pubAreaSize;
if (argc >= 2) {
if (XSTRNCMP(argv[1], "-?", 2) == 0 ||
@ -147,12 +150,32 @@ int TPM2_NVRAM_Store_Example(void* userCtx, int argc, char *argv[])
TPM2_DEMO_NVRAM_STORE_INDEX);
if (partialStore != PRIVATE_PART_ONLY) {
printf("Public part = %lu bytes\n", sizeof(keyBlob.pub));
printf("Public part = %hu bytes\n", keyBlob.pub.size);
rc = wolfTPM2_NVWriteAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_INDEX,
(byte*)&keyBlob.pub, sizeof(keyBlob.pub), 0);
(byte*)&keyBlob.pub.size, sizeof(keyBlob.pub.size), 0);
if (rc != 0) goto exit;
printf("Stored 2-byte size marker before the private part\n");
offset += sizeof(keyBlob.pub.size);
/* Necessary for storing the publicArea with the correct byte encoding */
rc = TPM2_AppendPublic(pubAreaBuffer, sizeof(pubAreaBuffer), &pubAreaSize, &keyBlob.pub);
/* Note:
* Public Area is the only part of a TPM key that can be stored encoded
* Private Area is stored as-is, because TPM2B_PRIVATE is byte buffer
* and UINT16 size field, while Public Area is a complex TCG structure.
*/
if (rc != TPM_RC_SUCCESS) {
printf("Encoding of the publicArea failed. Unable to store.\n");
goto exit;
}
/* The buffer holds pub.publicArea and also pub.size(UINT16) */
rc = wolfTPM2_NVWriteAuth(&dev, &nv, TPM2_DEMO_NVRAM_STORE_INDEX,
pubAreaBuffer, sizeof(UINT16) + keyBlob.pub.size, offset);
if (rc != 0) goto exit;
printf("NV write of public part succeeded\n\n");
offset = sizeof(keyBlob.pub);
offset += sizeof(UINT16) + keyBlob.pub.size;
#ifdef WOLFTPM_DEBUG_VERBOSE
TPM2_PrintPublicArea(&keyBlob.pub);
printf("\n");

View File

@ -42,11 +42,26 @@ int writeKeyBlob(const char* filename,
#if !defined(NO_FILESYSTEM) && !defined(NO_WRITE_TEMP_FILES)
XFILE fp = NULL;
size_t fileSz = 0;
byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
int pubAreaSize;
fp = XFOPEN(filename, "wb");
if (fp != XBADFILE) {
key->pub.size = sizeof(key->pub);
fileSz += XFWRITE(&key->pub, 1, sizeof(key->pub), fp);
/* Make publicArea in encoded format to eliminate empty fields, save space */
rc = TPM2_AppendPublic(pubAreaBuffer, sizeof(pubAreaBuffer), &pubAreaSize, &key->pub);
if (rc != TPM_RC_SUCCESS) return rc;
if (pubAreaSize != (key->pub.size + sizeof(key->pub.size))) {
#ifdef DEBUG_WOLFTPM
printf("writeKeyBlob: Sanity check for publicArea size failed\n");
#endif
return -1;
}
TPM2_PrintBin(pubAreaBuffer, pubAreaSize);
/* Write size marker for the public part */
fileSz += XFWRITE(&key->pub.size, 1, sizeof(key->pub.size), fp);
/* Write the public part with bytes aligned */
fileSz += XFWRITE(pubAreaBuffer, 1, sizeof(UINT16) + key->pub.size, fp);
/* Write the private part, size marker is included */
fileSz += XFWRITE(&key->priv, 1, sizeof(UINT16) + key->priv.size, fp);
XFCLOSE(fp);
}
@ -65,6 +80,8 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key)
XFILE fp = NULL;
size_t fileSz = 0;
size_t bytes_read = 0;
byte pubAreaBuffer[sizeof(TPM2B_PUBLIC)];
int pubAreaSize;
XMEMSET(key, 0, sizeof(WOLFTPM2_KEYBLOB));
@ -79,13 +96,29 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key)
}
printf("Reading %d bytes from %s\n", (int)fileSz, filename);
bytes_read = XFREAD(&key->pub, 1, sizeof(key->pub), fp);
if (bytes_read != sizeof(key->pub)) {
printf("Read %zu, expected public blob %zu bytes\n", bytes_read, sizeof(key->pub));
bytes_read = XFREAD(&key->pub.size, 1, sizeof(key->pub.size), fp);
if (bytes_read != sizeof(key->pub.size)) {
printf("Read %zu, expected size marker of %zu bytes\n", bytes_read, sizeof(key->pub.size));
goto exit;
}
if (fileSz > sizeof(key->pub)) {
fileSz -= sizeof(key->pub);
fileSz -= bytes_read;
bytes_read = XFREAD(pubAreaBuffer, 1, sizeof(UINT16) + key->pub.size, fp);
if (bytes_read != sizeof(UINT16) + key->pub.size) {
printf("Read %zu, expected public blob %lu bytes\n", bytes_read, sizeof(UINT16) + key->pub.size);
goto exit;
}
fileSz -= bytes_read; /* Reminder bytes for private key part */
/* Decode the byte stream into a publicArea structure ready for use */
rc = TPM2_ParsePublic(&key->pub, pubAreaBuffer, sizeof(pubAreaBuffer), &pubAreaSize);
if (rc != TPM_RC_SUCCESS) return rc;
#ifdef DEBUG_WOLFTPM
TPM2_PrintPublicArea(&key->pub);
#endif
if (fileSz > 0) {
printf("Reading the private part of the key\n");
bytes_read = XFREAD(&key->priv, 1, fileSz, fp);
if (bytes_read != fileSz) {
printf("Read %zu, expected private blob %zu bytes\n", bytes_read, fileSz);
@ -95,7 +128,8 @@ int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key)
}
/* sanity check the sizes */
if (key->pub.size != sizeof(key->pub) || key->priv.size > sizeof(key->priv.buffer)) {
if (pubAreaSize != (key->pub.size + sizeof(key->pub.size)) ||
key->priv.size > sizeof(key->priv.buffer)) {
printf("Struct size check failed (pub %d, priv %d)\n",
key->pub.size, key->priv.size);
rc = BUFFER_E;

View File

@ -5733,6 +5733,52 @@ int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size)
#endif
}
WOLFTPM_API int TPM2_AppendPublic(byte* buf, size_t size, int* sizeUsed, TPM2B_PUBLIC* pub)
{
TPM2_Packet packet;
if (buf == NULL || sizeUsed == NULL)
return BAD_FUNC_ARG;
if (size < sizeof(TPM2B_PUBLIC)) {
printf("Insufficient buffer size for TPM2B_PUBLIC operations\n");
return TPM_RC_FAILURE;
}
/* Prepare temporary buffer */
packet.buf = buf;
packet.pos = 0;
packet.size = (int)size;
TPM2_Packet_AppendPublic(&packet, pub);
*sizeUsed = packet.pos;
return TPM_RC_SUCCESS;
}
WOLFTPM_API int TPM2_ParsePublic(TPM2B_PUBLIC* pub, byte* buf, size_t size, int* sizeUsed)
{
TPM2_Packet packet;
if (buf == NULL || sizeUsed == NULL)
return BAD_FUNC_ARG;
if (size < sizeof(TPM2B_PUBLIC)) {
printf("Insufficient buffer size for TPM2B_PUBLIC operations\n");
return TPM_RC_FAILURE;
}
/* Prepare temporary buffer */
packet.buf = buf;
packet.pos = 0;
packet.size = (int)size;
TPM2_Packet_ParsePublic(&packet, pub);
*sizeUsed = packet.pos;
return TPM_RC_SUCCESS;
}
#ifdef DEBUG_WOLFTPM
#define LINE_LEN 16
void TPM2_PrintBin(const byte* buffer, word32 length)
@ -5864,7 +5910,7 @@ void TPM2_PrintPublicArea(const TPM2B_PUBLIC* pub)
TPM2_PrintBin(pub->publicArea.unique.derive.context.buffer, pub->publicArea.unique.derive.context.size);
break;
}
printf("\n");
}
#endif

View File

@ -2800,8 +2800,10 @@ WOLFTPM_API int TPM2_GetTpmCurve(int curveID);
WOLFTPM_API int TPM2_GetWolfCurve(int curve_id);
WOLFTPM_API int TPM2_ParseAttest(const TPM2B_ATTEST* in, TPMS_ATTEST* out);
WOLFTPM_LOCAL int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2B_NAME* name);
WOLFTPM_API int TPM2_HashNvPublic(TPMS_NV_PUBLIC* nvPublic, byte* buffer, UINT16* size);
WOLFTPM_API int TPM2_AppendPublic(byte* buf, size_t size, int* sizeUsed, TPM2B_PUBLIC* pub);
WOLFTPM_API int TPM2_ParsePublic(TPM2B_PUBLIC* pub, byte* buf, size_t size, int* sizeUsed);
WOLFTPM_LOCAL int TPM2_GetName(TPM2_CTX* ctx, UINT32 handleValue, int handleCnt, int idx, TPM2B_NAME* name);
#ifdef WOLFTPM2_USE_WOLF_RNG
WOLFTPM_API int TPM2_GetWolfRng(WC_RNG** rng);