/* SPDX-License-Identifier: BSD-2-Clause */ /*********************************************************************** * Copyright (c) 2015 - 2017, Intel Corporation * * All rights reserved. ***********************************************************************/ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "tss2_mu.h" #include "util/tpm2b.h" #include "util/tss2_endian.h" #define LOGMODULE marshal #include "util/log.h" #define TPM2B_MARSHAL(type) \ TSS2_RC Tss2_MU_##type##_Marshal(type const *src, uint8_t buffer[], \ size_t buffer_size, size_t *offset) \ { \ size_t local_offset = 0; \ TSS2_RC rc; \ \ if (src == NULL) { \ LOG_WARNING("src param is NULL"); \ return TSS2_MU_RC_BAD_REFERENCE; \ } \ if (offset != NULL) { \ LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \ local_offset = *offset; \ } \ if (buffer == NULL && offset == NULL) { \ LOG_WARNING("buffer and offset parameter are NULL"); \ return TSS2_MU_RC_BAD_REFERENCE; \ } else if (buffer == NULL && offset != NULL) { \ *offset += sizeof(src->size) + src->size; \ LOG_TRACE("buffer NULL and offset non-NULL, updating offset to %zu", \ *offset); \ return TSS2_RC_SUCCESS; \ } else if (buffer_size < local_offset || \ buffer_size - local_offset < (sizeof(src->size) + src->size)) { \ LOG_WARNING(\ "buffer_size: %zu with offset: %zu are insufficient for object " \ "of size %zu", \ buffer_size, \ local_offset, \ sizeof(src->size) + src->size); \ return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ } else if ((sizeof(type) - sizeof(src->size)) < src->size) { \ LOG_WARNING(\ "size: %u for buffer of " #type " is larger than max length" \ " of buffer: %zu", \ src->size, \ (sizeof(type) - sizeof(src->size))); \ return TSS2_MU_RC_BAD_SIZE; \ } \ \ LOG_DEBUG(\ "Marshalling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \ " at index 0x%zx, buffer size %zu, object size %u", \ (uintptr_t)&src, \ (uintptr_t)buffer, \ local_offset, \ buffer_size, \ src->size); \ \ rc = Tss2_MU_UINT16_Marshal(src->size, buffer, buffer_size, &local_offset); \ if (rc) \ return rc; \ \ if (src->size) { \ memcpy(&buffer[local_offset], ((TPM2B *)src)->buffer, src->size); \ local_offset += src->size; \ } \ \ if (offset != NULL) { \ *offset = local_offset; \ LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \ } \ \ return TSS2_RC_SUCCESS; \ } #define TPM2B_UNMARSHAL(type, buf_name) \ TSS2_RC Tss2_MU_##type##_Unmarshal(uint8_t const buffer[], size_t buffer_size, \ size_t *offset, type *dest) \ { \ size_t local_offset = 0; \ UINT16 size = 0; \ TSS2_RC rc; \ \ if (offset != NULL) { \ LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \ local_offset = *offset; \ } \ \ if (buffer == NULL || (dest == NULL && offset == NULL)) { \ LOG_WARNING("buffer or dest and offset parameter are NULL"); \ return TSS2_MU_RC_BAD_REFERENCE; \ } else if (buffer_size < local_offset || \ sizeof(size) > buffer_size - local_offset) \ { \ LOG_WARNING(\ "buffer_size: %zu with offset: %zu are insufficient for object " \ "of size %zu", \ buffer_size, \ local_offset, \ sizeof(size)); \ return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ } \ \ rc = Tss2_MU_UINT16_Unmarshal(buffer, buffer_size, &local_offset, &size); \ if (rc) \ return rc; \ \ LOG_DEBUG(\ "Unmarshaling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \ " at index 0x%zx, buffer size %zu, object size %u", \ (uintptr_t)buffer, \ (uintptr_t)dest, \ local_offset, \ buffer_size, \ size); \ \ if (size > buffer_size - local_offset) { \ LOG_WARNING(\ "buffer_size: %zu with offset: %zu are insufficient for object " \ "of size %zu", \ buffer_size, \ local_offset, \ (size_t)size); \ return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ } \ if (sizeof(dest->buf_name) < size) { \ LOG_ERROR("The dest field size of %zu is too small to unmarshal %d bytes", \ sizeof(dest->buf_name), size); \ return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ } \ \ if (dest != NULL) { \ dest->size = size; \ memcpy(((TPM2B *)dest)->buffer, &buffer[local_offset], size); \ } \ local_offset += size; \ if (offset != NULL) { \ *offset = local_offset; \ LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \ } \ \ return TSS2_RC_SUCCESS; \ } #define TPM2B_MARSHAL_SUBTYPE(type, subtype, member) \ TSS2_RC Tss2_MU_##type##_Marshal(type const *src, uint8_t buffer[], \ size_t buffer_size, size_t *offset) \ { \ size_t local_offset = 0; \ UINT8 *ptr = NULL; \ TSS2_RC rc; \ \ if (src == NULL) { \ LOG_WARNING("src param is NULL"); \ return TSS2_MU_RC_BAD_REFERENCE; \ } \ \ if (offset != NULL) { \ LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \ local_offset = *offset; \ } \ \ if (buffer == NULL && offset == NULL) { \ LOG_WARNING("buffer and offset parameter are NULL"); \ return TSS2_MU_RC_BAD_REFERENCE; \ } else if (buffer_size < local_offset || \ buffer_size - local_offset < sizeof(src->size)) { \ LOG_WARNING(\ "buffer_size: %zu with offset: %zu are insufficient for object " \ "of size %zu", \ buffer_size, \ local_offset, \ sizeof(src->size)); \ return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ } \ \ if (buffer) \ ptr = &buffer[local_offset]; \ \ LOG_DEBUG(\ "Marshalling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \ " at index 0x%zx, buffer size %zu, object size %u", \ (uintptr_t)&src, \ (uintptr_t)buffer, \ local_offset, \ buffer_size, \ src->size); \ \ rc = Tss2_MU_UINT16_Marshal(src->size, buffer, buffer_size, &local_offset); \ if (rc) \ return rc; \ \ rc = Tss2_MU_##subtype##_Marshal(&src->member, buffer, buffer_size, &local_offset); \ if (rc) \ return rc; \ \ /* Update the size to the real value */ \ if (buffer) \ *(UINT16 *)ptr = HOST_TO_BE_16(buffer + local_offset - ptr - 2); \ \ if (offset != NULL) { \ *offset = local_offset; \ LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \ } \ \ return TSS2_RC_SUCCESS; \ } #define TPM2B_UNMARSHAL_SUBTYPE(type, subtype, member) \ TSS2_RC Tss2_MU_##type##_Unmarshal(uint8_t const buffer[], size_t buffer_size, \ size_t *offset, type *dest) \ { \ size_t local_offset = 0; \ UINT16 size = 0; \ TSS2_RC rc; \ \ if (offset != NULL) { \ LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \ local_offset = *offset; \ } \ \ if (buffer == NULL || (dest == NULL && offset == NULL)) { \ LOG_WARNING("buffer or dest and offset parameter are NULL"); \ return TSS2_MU_RC_BAD_REFERENCE; \ } else if (buffer_size < local_offset || \ sizeof(size) > buffer_size - local_offset) \ { \ LOG_WARNING(\ "buffer_size: %zu with offset: %zu are insufficient for object " \ "of size %zu", \ buffer_size, \ local_offset, \ sizeof(size)); \ return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ } \ if (dest && dest->size != 0) { \ LOG_WARNING("Size not zero"); \ return TSS2_SYS_RC_BAD_VALUE; \ } \ \ rc = Tss2_MU_UINT16_Unmarshal(buffer, buffer_size, &local_offset, &size); \ if (rc) \ return rc; \ LOG_DEBUG(\ "Unmarshaling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \ " at index 0x%zx, buffer size %zu, object size %u", \ (uintptr_t)buffer, \ (uintptr_t)dest, \ local_offset, \ buffer_size, \ size); \ \ if (size > buffer_size - local_offset) { \ LOG_WARNING(\ "buffer_size: %zu with offset: %zu are insufficient for object " \ "of size %zu", \ buffer_size, \ local_offset, \ (size_t)size); \ return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ } \ if (sizeof(dest->member) < size) { \ LOG_ERROR("The dest field size of %zu is too small to unmarshal %d bytes", \ sizeof(dest->member), size); \ return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ } \ \ if (dest != NULL) { \ dest->size = size; \ Tss2_MU_##subtype##_Unmarshal(buffer, buffer_size, &local_offset, &dest->member); \ if (rc) \ return rc; \ } else { \ local_offset += size; \ } \ \ if (offset != NULL) { \ *offset = local_offset; \ LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \ } \ \ return TSS2_RC_SUCCESS; \ } /* * These macros expand to (un)marshal functions for each of the TPM2B types * the specification part 2. */ TPM2B_MARSHAL (TPM2B_DIGEST); TPM2B_UNMARSHAL(TPM2B_DIGEST, buffer); TPM2B_MARSHAL (TPM2B_DATA); TPM2B_UNMARSHAL(TPM2B_DATA, buffer); TPM2B_MARSHAL (TPM2B_EVENT); TPM2B_UNMARSHAL(TPM2B_EVENT, buffer); TPM2B_MARSHAL (TPM2B_MAX_BUFFER); TPM2B_UNMARSHAL(TPM2B_MAX_BUFFER, buffer); TPM2B_MARSHAL (TPM2B_MAX_NV_BUFFER); TPM2B_UNMARSHAL(TPM2B_MAX_NV_BUFFER, buffer); TPM2B_MARSHAL (TPM2B_IV); TPM2B_UNMARSHAL(TPM2B_IV, buffer); TPM2B_MARSHAL (TPM2B_NAME); TPM2B_UNMARSHAL(TPM2B_NAME, name); TPM2B_MARSHAL (TPM2B_ATTEST); TPM2B_UNMARSHAL(TPM2B_ATTEST, attestationData); TPM2B_MARSHAL (TPM2B_SYM_KEY); TPM2B_UNMARSHAL(TPM2B_SYM_KEY, buffer); TPM2B_MARSHAL (TPM2B_SENSITIVE_DATA); TPM2B_UNMARSHAL(TPM2B_SENSITIVE_DATA, buffer); TPM2B_MARSHAL (TPM2B_PUBLIC_KEY_RSA); TPM2B_UNMARSHAL(TPM2B_PUBLIC_KEY_RSA, buffer); TPM2B_MARSHAL (TPM2B_PRIVATE_KEY_RSA); TPM2B_UNMARSHAL(TPM2B_PRIVATE_KEY_RSA, buffer); TPM2B_MARSHAL (TPM2B_ECC_PARAMETER); TPM2B_UNMARSHAL(TPM2B_ECC_PARAMETER, buffer); TPM2B_MARSHAL (TPM2B_ENCRYPTED_SECRET); TPM2B_UNMARSHAL(TPM2B_ENCRYPTED_SECRET, secret); TPM2B_MARSHAL (TPM2B_PRIVATE_VENDOR_SPECIFIC); TPM2B_UNMARSHAL(TPM2B_PRIVATE_VENDOR_SPECIFIC, buffer); TPM2B_MARSHAL (TPM2B_PRIVATE); TPM2B_UNMARSHAL(TPM2B_PRIVATE, buffer); TPM2B_MARSHAL (TPM2B_ID_OBJECT); TPM2B_UNMARSHAL(TPM2B_ID_OBJECT, credential); TPM2B_MARSHAL (TPM2B_CONTEXT_SENSITIVE); TPM2B_UNMARSHAL(TPM2B_CONTEXT_SENSITIVE, buffer); TPM2B_MARSHAL (TPM2B_CONTEXT_DATA); TPM2B_UNMARSHAL(TPM2B_CONTEXT_DATA, buffer); TPM2B_MARSHAL (TPM2B_NONCE); TPM2B_UNMARSHAL(TPM2B_NONCE, buffer); TPM2B_MARSHAL (TPM2B_TIMEOUT); TPM2B_UNMARSHAL(TPM2B_TIMEOUT, buffer); TPM2B_MARSHAL (TPM2B_AUTH); TPM2B_UNMARSHAL(TPM2B_AUTH, buffer); TPM2B_MARSHAL (TPM2B_OPERAND); TPM2B_UNMARSHAL(TPM2B_OPERAND, buffer); TPM2B_MARSHAL (TPM2B_TEMPLATE); TPM2B_UNMARSHAL(TPM2B_TEMPLATE, buffer); TPM2B_MARSHAL_SUBTYPE(TPM2B_ECC_POINT, TPMS_ECC_POINT, point); TPM2B_UNMARSHAL_SUBTYPE(TPM2B_ECC_POINT, TPMS_ECC_POINT, point); TPM2B_MARSHAL_SUBTYPE(TPM2B_NV_PUBLIC, TPMS_NV_PUBLIC, nvPublic); TPM2B_UNMARSHAL_SUBTYPE(TPM2B_NV_PUBLIC, TPMS_NV_PUBLIC, nvPublic); TPM2B_MARSHAL_SUBTYPE(TPM2B_SENSITIVE, TPMT_SENSITIVE, sensitiveArea); TPM2B_UNMARSHAL_SUBTYPE(TPM2B_SENSITIVE, TPMT_SENSITIVE, sensitiveArea); TPM2B_MARSHAL_SUBTYPE(TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE, sensitive); TPM2B_UNMARSHAL_SUBTYPE(TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE, sensitive); TPM2B_MARSHAL_SUBTYPE(TPM2B_CREATION_DATA, TPMS_CREATION_DATA, creationData); TPM2B_UNMARSHAL_SUBTYPE(TPM2B_CREATION_DATA, TPMS_CREATION_DATA, creationData); TPM2B_MARSHAL_SUBTYPE(TPM2B_PUBLIC, TPMT_PUBLIC, publicArea); TPM2B_UNMARSHAL_SUBTYPE(TPM2B_PUBLIC, TPMT_PUBLIC, publicArea);