blob: c21aea0bded3051083de00b4600038fca245a3a3 [file] [log] [blame]
/* SPDX-License-Identifier: BSD-2-Clause */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#define LOGMODULE test
#include "tss2_sys.h"
#include "tss2_tcti.h"
#include "tss2/tss2_tcti_spi_helper.h"
#include "util/log.h"
#include "test.h"
typedef struct fuzz_user_data fuzz_user_data;
struct fuzz_user_data {
size_t len;
const uint8_t *fuzz_data;
};
typedef enum {
TPM_DID_VID_HEAD = 0,
TPM_DID_VID_BODY,
TPM_ACCESS_HEAD,
TPM_ACCESS_BODY,
TPM_STS_HEAD,
TPM_STS_BODY,
TPM_RID_HEAD,
TPM_RID_BODY
} tpm_state_t;
static const unsigned char TPM_DID_VID_0[] = {0x83, 0xd4, 0x0f, 0x00, 0xd1, 0x15, 0x1b, 0x00};
static const unsigned char TPM_ACCESS_0[] = {0x80, 0xd4, 0x00, 0x00, 0xa1};
static const unsigned char TPM_STS_0[] = {0x83, 0xd4, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00};
static const unsigned char TPM_RID_0[] = {0x80, 0xd4, 0x0f, 0x04, 0x00};
static bool is_init = true;
TSS2_RC platform_sleep_ms (void* user_data, int32_t milliseconds)
{
UNUSED(user_data);
UNUSED(milliseconds);
return TSS2_RC_SUCCESS;
}
TSS2_RC platform_start_timeout (void* user_data, int32_t milliseconds)
{
UNUSED(user_data);
UNUSED(milliseconds);
return TSS2_RC_SUCCESS;
}
TSS2_RC platform_timeout_expired (void* user_data, bool *is_timeout_expired)
{
UNUSED(user_data);
*is_timeout_expired = true;
return TSS2_RC_SUCCESS;
}
TSS2_RC platform_spi_acquire (void* user_data)
{
UNUSED(user_data);
return TSS2_RC_SUCCESS;
}
TSS2_RC platform_spi_release (void* user_data)
{
UNUSED(user_data);
return TSS2_RC_SUCCESS;
}
TSS2_RC platform_spi_transfer_with_wait_state (void* user_data, const void *data_out, void *data_in, size_t cnt)
{
UNUSED(user_data);
UNUSED(data_out);
UNUSED(cnt);
static tpm_state_t tpm_state = TPM_DID_VID_HEAD;
switch (tpm_state++) {
case TPM_DID_VID_HEAD:
memcpy (data_in, TPM_DID_VID_0, 4);
((unsigned char *)data_in)[3] |= 0x01;
break;
case TPM_DID_VID_BODY:
memcpy (data_in, TPM_DID_VID_0 + 4, sizeof (TPM_DID_VID_0) - 4);
break;
case TPM_ACCESS_HEAD:
memcpy (data_in, TPM_ACCESS_0, 4);
((unsigned char *)data_in)[3] |= 0x01;
break;
case TPM_ACCESS_BODY:
memcpy (data_in, TPM_ACCESS_0 + 4, sizeof (TPM_ACCESS_0) - 4);
break;
case TPM_STS_HEAD:
memcpy (data_in, TPM_STS_0, 4);
((unsigned char *)data_in)[3] |= 0x01;
break;
case TPM_STS_BODY:
memcpy (data_in, TPM_STS_0 + 4, sizeof (TPM_STS_0) - 4);
break;
case TPM_RID_HEAD:
memcpy (data_in, TPM_RID_0, 4);
((unsigned char *)data_in)[3] |= 0x01;
break;
case TPM_RID_BODY:
memcpy (data_in, TPM_RID_0 + 4, 1);
break;
default:
return TSS2_TCTI_RC_IO_ERROR;
}
return TSS2_RC_SUCCESS;
}
TSS2_RC platform_spi_transfer_fuzz (void* user_data, const void *data_out, void *data_in, size_t cnt)
{
UNUSED(data_out);
fuzz_user_data *udata = (fuzz_user_data *)user_data;
/* libfuzzer input might only be 2 bytes, but cnt might be 32 */
size_t min = cnt > udata->len ? cnt : udata->len;
memcpy(data_in, udata->fuzz_data, min);
return TSS2_RC_SUCCESS;
}
TSS2_RC platform_spi_transfer (void* user_data, const void *data_out, void *data_in, size_t cnt)
{
/*
* Use if we're past init to start fuzzing
*/
return is_init ?
platform_spi_transfer_with_wait_state(user_data, data_out, data_in, cnt) :
platform_spi_transfer_fuzz(user_data, data_out, data_in, cnt);
}
void platform_finalize(void* user_data)
{
UNUSED(user_data);
}
int
LLVMFuzzerTestOneInput (
const uint8_t *fuzz_data,
size_t size)
{
if (!fuzz_data) {
return -1;
}
TSS2_TCTI_CONTEXT *tcti_ctx = NULL;
TSS2_SYS_CONTEXT *sapi_ctx = NULL;
fuzz_user_data udata = {
.len = size,
.fuzz_data = fuzz_data
};
TSS2_TCTI_SPI_HELPER_PLATFORM conf = {
.user_data = &udata,
.sleep_ms = platform_sleep_ms,
.start_timeout = platform_start_timeout,
.timeout_expired = platform_timeout_expired,
.spi_acquire = platform_spi_acquire,
.spi_release = platform_spi_release,
.spi_transfer = platform_spi_transfer,
.finalize = platform_finalize
};
size_t tcti_size = 0;
TSS2_RC rc = Tss2_Tcti_Spi_Helper_Init (
NULL, &tcti_size, &conf);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR("Tss2_Tcti_Spi_Helper_Init failed 0x%x", rc);
return EXIT_FAILURE;
}
tcti_ctx = (TSS2_TCTI_CONTEXT *)calloc(1, tcti_size);
if (!tcti_ctx) {
LOG_ERROR("OOM allocating TCTI");
goto error;
}
rc = Tss2_Tcti_Spi_Helper_Init (
tcti_ctx, &tcti_size, &conf);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR("Tss2_Tcti_Spi_Helper_Init failed 0x%x", rc);
goto error;
}
is_init = false;
size_t sapi_size = Tss2_Sys_GetContextSize(0);
sapi_ctx = (TSS2_SYS_CONTEXT *)calloc(1, sapi_size);
if (!sapi_ctx) {
LOG_ERROR("OOM allocating SAPI");
goto error;
}
rc = Tss2_Sys_Initialize(sapi_ctx, sapi_size, tcti_ctx, NULL);
if (rc != TSS2_RC_SUCCESS) {
LOG_ERROR("Tss2_Sys_Initialize failed 0x%x", rc);
goto error;
}
/*
* ignore the RC (we expect jibberish from the TCTI)
* but this should get the TCTI firing through transfer.
*/
TPM2B_DIGEST buf = { 0 };
UNUSED(Tss2_Sys_GetRandom(sapi_ctx, NULL, 4, &buf, NULL));
error:
Tss2_Sys_Finalize(sapi_ctx);
free(sapi_ctx);
Tss2_Tcti_Finalize(tcti_ctx);
free(tcti_ctx);
return 0;
}