tpm2: NVMarshal: Introduce MAX_MARSHALLED_OBJECT_SIZE

Introduce the #define MAX_MARSHALLED_OBJECT_SIZE to be used for a size of
a byte buffer that is supposed to hold a marshalled OBJECT. The number
is not exact but provides for a 'safe' size of a buffer.

Add a test case to check that MAX_MARSHALLED_OBJECT_SIZE is sufficient.
The test case needs access to ANY_OBJECT_Marshal, which is only available
when -static can be used for linking since otherwise the function is
private to the library. Static linking the test case does not work when
test-coverage is enabled, therefore disable statically linked test cases
in when test-coverage is enabled and give control to the user to disable
statically linked test cases in other cases as well.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
Stefan Berger 2024-01-13 16:19:39 -05:00 committed by Stefan Berger
parent 37f8e2f2c8
commit bb4dafb1e7
5 changed files with 130 additions and 0 deletions

1
.gitignore vendored
View File

@ -53,6 +53,7 @@ Makefile
/tests/fuzz
/tests/freebl_sha1flattensize
/tests/nvram_offsets
/tests/object_size
/tests/tpm2_createprimary
/tests/tpm2_cve-2023-1017
/tests/tpm2_cve-2023-1018

View File

@ -267,11 +267,24 @@ AC_ARG_ENABLE([test-coverage],
[if test "$enableval" = "yes"; then
COVERAGE_CFLAGS="-fprofile-arcs -ftest-coverage"
COVERAGE_LDFLAGS="-fprofile-arcs"
enable_static_tests=no # some tests will not link
fi], [
enable_test_coverage=no
]
)
AC_ARG_ENABLE([static-tests],
AS_HELP_STRING([--disable-static-tests], [Disable statically linked tests]),
[if test "$enableval" = "yes"; then
AM_CONDITIONAL(ENABLE_STATIC_TESTS, true)
else
AM_CONDITIONAL(ENABLE_STATIC_TESTS, false)
fi], [
AM_CONDITIONAL(ENABLE_STATIC_TESTS, true)
enable_static_tests=yes
]
)
LT_INIT
AC_PROG_CC
AC_PROG_CXX
@ -372,5 +385,6 @@ echo "With TPM2 support : $with_tpm2"
echo "HAVE_VERSION_SCRIPT : $have_version_script"
echo "Use openssl crypto for : $use_openssl_functions_for"
echo "Test coverage : $enable_test_coverage"
echo "Statically linked tests : $enable_static_tests"
echo
echo

View File

@ -46,6 +46,11 @@
#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
// Maximum size of buffer ANY_OBJECT_Marshal() will require to marshal an OBJECT
// This is not an exact number but gives a 'safe' buffer size
#define MAX_MARSHALLED_OBJECT_SIZE \
(sizeof(OBJECT) + 32 /* marshalling headers */)
UINT16 VolatileState_Marshal(BYTE **buffer, INT32 *size);
TPM_RC VolatileState_Unmarshal(BYTE **buffer, INT32 *size);

View File

@ -48,6 +48,29 @@ nvram_offsets_CFLAGS = $(AM_CFLAGS) \
-DTPM_POSIX
nvram_offsets_LDFLAGS = $(AM_LDFLAGS)
if WITH_TPM2
if ENABLE_STATIC_TESTS
# object_size needs ANY_OBJECT_Marshal which only is accessible with '-static'
check_PROGRAMS += \
object_size
TESTS += \
object_size
object_size_SOURCES = object_size.c
object_size_CFLAGS = $(AM_CFLAGS) \
-static \
-I$(top_srcdir)/include/libtpms \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/tpm2 \
-I$(top_srcdir)/src/tpm2/crypto \
-I$(top_srcdir)/src/tpm2/crypto/openssl \
-DTPM_POSIX
object_size_LDFLAGS = $(AM_LDFLAGS)
endif # ENABLE_STATIC_TESTS
endif # WITH_TPM2
if WITH_TPM2
check_PROGRAMS += fuzz
endif

87
tests/object_size.c Normal file
View File

@ -0,0 +1,87 @@
#include <assert.h>
#include <stdlib.h>
#include "Tpm.h"
int main(void)
{
/* This is supposed to be the OBJECT that requires the most bytes
* when it is marshalled: currently an RSA key
*/
OBJECT object = {
.attributes = {
.occupied = SET,
},
.publicArea = {
.type = TPM_ALG_RSA,
.nameAlg = TPM_ALG_SHA512,
.objectAttributes = 0,
.authPolicy.t = {
.size = sizeof(object.publicArea.authPolicy.t.buffer),
},
.parameters.rsaDetail = {
.symmetric = {
.algorithm = TPM_ALG_AES,
.keyBits = 256,
.mode = TPM_ALG_ECB,
},
.scheme = TPM_ALG_RSAPSS,
.keyBits = MAX_RSA_KEY_BITS,
.exponent = 0x10001,
},
.unique.rsa.t = {
.size = sizeof(object.publicArea.unique.rsa.t.buffer),
},
},
.sensitive = {
.sensitiveType = TPM_ALG_RSA,
.authValue.t = {
.size = sizeof(object.sensitive.authValue.t.buffer),
},
.seedValue.t = {
.size = sizeof(object.sensitive.seedValue.t.buffer),
},
.sensitive.rsa.t = {
.size = sizeof(object.sensitive.sensitive.rsa.t.buffer),
},
},
.privateExponent = {
.Q = {
.size = CRYPT_WORDS(BITS_TO_BYTES(MAX_RSA_KEY_BITS / 2)),
},
.dP = {
.size = CRYPT_WORDS(BITS_TO_BYTES(MAX_RSA_KEY_BITS / 2)),
},
.dQ = {
.size = CRYPT_WORDS(BITS_TO_BYTES(MAX_RSA_KEY_BITS / 2)),
},
.qInv = {
.size = CRYPT_WORDS(BITS_TO_BYTES(MAX_RSA_KEY_BITS / 2)),
},
},
.qualifiedName.t = {
.size = sizeof(object.qualifiedName.t.name),
},
.evictHandle = 0x12345678,
.name.t = {
.size = sizeof(object.name.t.name),
},
.seedCompatLevel = 1,
};
/* this buffer must only be filled to <= MAX_MARSHALLED_OBJECT_SIZE bytes */
BYTE buffer[2 * MAX_MARSHALLED_OBJECT_SIZE];
BYTE *buf = buffer;
INT32 size = sizeof(buffer);
UINT32 written;
written = ANY_OBJECT_Marshal(&object, &buf, &size);
if (written > MAX_MARSHALLED_OBJECT_SIZE) {
fprintf(stderr,
"Expected flattened OBJECT to have %zu bytes, but it has %u.\n",
MAX_MARSHALLED_OBJECT_SIZE, written);
return EXIT_FAILURE;
}
fprintf(stdout, " written = %d < MAX_MARSHALLED_OBJECT_SIZE = %zu\n",
written, MAX_MARSHALLED_OBJECT_SIZE);
return EXIT_SUCCESS;
}