1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /*********************************************************************** 3 * Copyright (c) 2015 - 2017, Intel Corporation 4 * 5 * All rights reserved. 6 ***********************************************************************/ 7 8 #ifdef HAVE_CONFIG_H 9 #include <config.h> 10 #endif 11 12 #include <inttypes.h> 13 #include <string.h> 14 15 #include "tss2_mu.h" 16 17 #include "util/tpm2b.h" 18 #include "util/tss2_endian.h" 19 #define LOGMODULE marshal 20 #include "util/log.h" 21 22 #define TPM2B_MARSHAL(type) \ 23 TSS2_RC Tss2_MU_##type##_Marshal(type const *src, uint8_t buffer[], \ 24 size_t buffer_size, size_t *offset) \ 25 { \ 26 size_t local_offset = 0; \ 27 TSS2_RC rc; \ 28 \ 29 if (src == NULL) { \ 30 LOG_WARNING("src param is NULL"); \ 31 return TSS2_MU_RC_BAD_REFERENCE; \ 32 } \ 33 if (offset != NULL) { \ 34 LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \ 35 local_offset = *offset; \ 36 } \ 37 if (buffer == NULL && offset == NULL) { \ 38 LOG_WARNING("buffer and offset parameter are NULL"); \ 39 return TSS2_MU_RC_BAD_REFERENCE; \ 40 } else if (buffer == NULL && offset != NULL) { \ 41 *offset += sizeof(src->size) + src->size; \ 42 LOG_TRACE("buffer NULL and offset non-NULL, updating offset to %zu", \ 43 *offset); \ 44 return TSS2_RC_SUCCESS; \ 45 } else if (buffer_size < local_offset || \ 46 buffer_size - local_offset < (sizeof(src->size) + src->size)) { \ 47 LOG_WARNING(\ 48 "buffer_size: %zu with offset: %zu are insufficient for object " \ 49 "of size %zu", \ 50 buffer_size, \ 51 local_offset, \ 52 sizeof(src->size) + src->size); \ 53 return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ 54 } else if ((sizeof(type) - sizeof(src->size)) < src->size) { \ 55 LOG_WARNING(\ 56 "size: %u for buffer of " #type " is larger than max length" \ 57 " of buffer: %zu", \ 58 src->size, \ 59 (sizeof(type) - sizeof(src->size))); \ 60 return TSS2_MU_RC_BAD_SIZE; \ 61 } \ 62 \ 63 LOG_DEBUG(\ 64 "Marshalling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \ 65 " at index 0x%zx, buffer size %zu, object size %u", \ 66 (uintptr_t)&src, \ 67 (uintptr_t)buffer, \ 68 local_offset, \ 69 buffer_size, \ 70 src->size); \ 71 \ 72 rc = Tss2_MU_UINT16_Marshal(src->size, buffer, buffer_size, &local_offset); \ 73 if (rc) \ 74 return rc; \ 75 \ 76 if (src->size) { \ 77 memcpy(&buffer[local_offset], ((TPM2B *)src)->buffer, src->size); \ 78 local_offset += src->size; \ 79 } \ 80 \ 81 if (offset != NULL) { \ 82 *offset = local_offset; \ 83 LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \ 84 } \ 85 \ 86 return TSS2_RC_SUCCESS; \ 87 } 88 89 #define TPM2B_UNMARSHAL(type, buf_name) \ 90 TSS2_RC Tss2_MU_##type##_Unmarshal(uint8_t const buffer[], size_t buffer_size, \ 91 size_t *offset, type *dest) \ 92 { \ 93 size_t local_offset = 0; \ 94 UINT16 size = 0; \ 95 TSS2_RC rc; \ 96 \ 97 if (offset != NULL) { \ 98 LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \ 99 local_offset = *offset; \ 100 } \ 101 \ 102 if (buffer == NULL || (dest == NULL && offset == NULL)) { \ 103 LOG_WARNING("buffer or dest and offset parameter are NULL"); \ 104 return TSS2_MU_RC_BAD_REFERENCE; \ 105 } else if (buffer_size < local_offset || \ 106 sizeof(size) > buffer_size - local_offset) \ 107 { \ 108 LOG_WARNING(\ 109 "buffer_size: %zu with offset: %zu are insufficient for object " \ 110 "of size %zu", \ 111 buffer_size, \ 112 local_offset, \ 113 sizeof(size)); \ 114 return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ 115 } \ 116 \ 117 rc = Tss2_MU_UINT16_Unmarshal(buffer, buffer_size, &local_offset, &size); \ 118 if (rc) \ 119 return rc; \ 120 \ 121 LOG_DEBUG(\ 122 "Unmarshaling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \ 123 " at index 0x%zx, buffer size %zu, object size %u", \ 124 (uintptr_t)buffer, \ 125 (uintptr_t)dest, \ 126 local_offset, \ 127 buffer_size, \ 128 size); \ 129 \ 130 if (size > buffer_size - local_offset) { \ 131 LOG_WARNING(\ 132 "buffer_size: %zu with offset: %zu are insufficient for object " \ 133 "of size %zu", \ 134 buffer_size, \ 135 local_offset, \ 136 (size_t)size); \ 137 return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ 138 } \ 139 if (sizeof(dest->buf_name) < size) { \ 140 LOG_ERROR("The dest field size of %zu is too small to unmarshal %d bytes", \ 141 sizeof(dest->buf_name), size); \ 142 return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ 143 } \ 144 \ 145 if (dest != NULL) { \ 146 dest->size = size; \ 147 memcpy(((TPM2B *)dest)->buffer, &buffer[local_offset], size); \ 148 } \ 149 local_offset += size; \ 150 if (offset != NULL) { \ 151 *offset = local_offset; \ 152 LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \ 153 } \ 154 \ 155 return TSS2_RC_SUCCESS; \ 156 } 157 158 #define TPM2B_MARSHAL_SUBTYPE(type, subtype, member) \ 159 TSS2_RC Tss2_MU_##type##_Marshal(type const *src, uint8_t buffer[], \ 160 size_t buffer_size, size_t *offset) \ 161 { \ 162 size_t local_offset = 0; \ 163 UINT8 *ptr = NULL; \ 164 TSS2_RC rc; \ 165 \ 166 if (src == NULL) { \ 167 LOG_WARNING("src param is NULL"); \ 168 return TSS2_MU_RC_BAD_REFERENCE; \ 169 } \ 170 \ 171 if (offset != NULL) { \ 172 LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \ 173 local_offset = *offset; \ 174 } \ 175 \ 176 if (buffer == NULL && offset == NULL) { \ 177 LOG_WARNING("buffer and offset parameter are NULL"); \ 178 return TSS2_MU_RC_BAD_REFERENCE; \ 179 } else if (buffer_size < local_offset || \ 180 buffer_size - local_offset < sizeof(src->size)) { \ 181 LOG_WARNING(\ 182 "buffer_size: %zu with offset: %zu are insufficient for object " \ 183 "of size %zu", \ 184 buffer_size, \ 185 local_offset, \ 186 sizeof(src->size)); \ 187 return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ 188 } \ 189 \ 190 if (buffer) \ 191 ptr = &buffer[local_offset]; \ 192 \ 193 LOG_DEBUG(\ 194 "Marshalling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \ 195 " at index 0x%zx, buffer size %zu, object size %u", \ 196 (uintptr_t)&src, \ 197 (uintptr_t)buffer, \ 198 local_offset, \ 199 buffer_size, \ 200 src->size); \ 201 \ 202 rc = Tss2_MU_UINT16_Marshal(src->size, buffer, buffer_size, &local_offset); \ 203 if (rc) \ 204 return rc; \ 205 \ 206 rc = Tss2_MU_##subtype##_Marshal(&src->member, buffer, buffer_size, &local_offset); \ 207 if (rc) \ 208 return rc; \ 209 \ 210 /* Update the size to the real value */ \ 211 if (buffer) \ 212 *(UINT16 *)ptr = HOST_TO_BE_16(buffer + local_offset - ptr - 2); \ 213 \ 214 if (offset != NULL) { \ 215 *offset = local_offset; \ 216 LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \ 217 } \ 218 \ 219 return TSS2_RC_SUCCESS; \ 220 } 221 222 #define TPM2B_UNMARSHAL_SUBTYPE(type, subtype, member) \ 223 TSS2_RC Tss2_MU_##type##_Unmarshal(uint8_t const buffer[], size_t buffer_size, \ 224 size_t *offset, type *dest) \ 225 { \ 226 size_t local_offset = 0; \ 227 UINT16 size = 0; \ 228 TSS2_RC rc; \ 229 \ 230 if (offset != NULL) { \ 231 LOG_DEBUG("offset non-NULL, initial value: %zu", *offset); \ 232 local_offset = *offset; \ 233 } \ 234 \ 235 if (buffer == NULL || (dest == NULL && offset == NULL)) { \ 236 LOG_WARNING("buffer or dest and offset parameter are NULL"); \ 237 return TSS2_MU_RC_BAD_REFERENCE; \ 238 } else if (buffer_size < local_offset || \ 239 sizeof(size) > buffer_size - local_offset) \ 240 { \ 241 LOG_WARNING(\ 242 "buffer_size: %zu with offset: %zu are insufficient for object " \ 243 "of size %zu", \ 244 buffer_size, \ 245 local_offset, \ 246 sizeof(size)); \ 247 return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ 248 } \ 249 if (dest && dest->size != 0) { \ 250 LOG_WARNING("Size not zero"); \ 251 return TSS2_SYS_RC_BAD_VALUE; \ 252 } \ 253 \ 254 rc = Tss2_MU_UINT16_Unmarshal(buffer, buffer_size, &local_offset, &size); \ 255 if (rc) \ 256 return rc; \ 257 LOG_DEBUG(\ 258 "Unmarshaling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \ 259 " at index 0x%zx, buffer size %zu, object size %u", \ 260 (uintptr_t)buffer, \ 261 (uintptr_t)dest, \ 262 local_offset, \ 263 buffer_size, \ 264 size); \ 265 \ 266 if (size > buffer_size - local_offset) { \ 267 LOG_WARNING(\ 268 "buffer_size: %zu with offset: %zu are insufficient for object " \ 269 "of size %zu", \ 270 buffer_size, \ 271 local_offset, \ 272 (size_t)size); \ 273 return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ 274 } \ 275 if (sizeof(dest->member) < size) { \ 276 LOG_ERROR("The dest field size of %zu is too small to unmarshal %d bytes", \ 277 sizeof(dest->member), size); \ 278 return TSS2_MU_RC_INSUFFICIENT_BUFFER; \ 279 } \ 280 \ 281 if (dest != NULL) { \ 282 dest->size = size; \ 283 Tss2_MU_##subtype##_Unmarshal(buffer, buffer_size, &local_offset, &dest->member); \ 284 if (rc) \ 285 return rc; \ 286 } else { \ 287 local_offset += size; \ 288 } \ 289 \ 290 if (offset != NULL) { \ 291 *offset = local_offset; \ 292 LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \ 293 } \ 294 \ 295 return TSS2_RC_SUCCESS; \ 296 } 297 298 /* 299 * These macros expand to (un)marshal functions for each of the TPM2B types 300 * the specification part 2. 301 */ 302 TPM2B_MARSHAL (TPM2B_DIGEST); 303 TPM2B_UNMARSHAL(TPM2B_DIGEST, buffer); 304 TPM2B_MARSHAL (TPM2B_DATA); 305 TPM2B_UNMARSHAL(TPM2B_DATA, buffer); 306 TPM2B_MARSHAL (TPM2B_EVENT); 307 TPM2B_UNMARSHAL(TPM2B_EVENT, buffer); 308 TPM2B_MARSHAL (TPM2B_MAX_BUFFER); 309 TPM2B_UNMARSHAL(TPM2B_MAX_BUFFER, buffer); 310 TPM2B_MARSHAL (TPM2B_MAX_NV_BUFFER); 311 TPM2B_UNMARSHAL(TPM2B_MAX_NV_BUFFER, buffer); 312 TPM2B_MARSHAL (TPM2B_IV); 313 TPM2B_UNMARSHAL(TPM2B_IV, buffer); 314 TPM2B_MARSHAL (TPM2B_NAME); 315 TPM2B_UNMARSHAL(TPM2B_NAME, name); 316 TPM2B_MARSHAL (TPM2B_ATTEST); 317 TPM2B_UNMARSHAL(TPM2B_ATTEST, attestationData); 318 TPM2B_MARSHAL (TPM2B_SYM_KEY); 319 TPM2B_UNMARSHAL(TPM2B_SYM_KEY, buffer); 320 TPM2B_MARSHAL (TPM2B_SENSITIVE_DATA); 321 TPM2B_UNMARSHAL(TPM2B_SENSITIVE_DATA, buffer); 322 TPM2B_MARSHAL (TPM2B_PUBLIC_KEY_RSA); 323 TPM2B_UNMARSHAL(TPM2B_PUBLIC_KEY_RSA, buffer); 324 TPM2B_MARSHAL (TPM2B_PRIVATE_KEY_RSA); 325 TPM2B_UNMARSHAL(TPM2B_PRIVATE_KEY_RSA, buffer); 326 TPM2B_MARSHAL (TPM2B_ECC_PARAMETER); 327 TPM2B_UNMARSHAL(TPM2B_ECC_PARAMETER, buffer); 328 TPM2B_MARSHAL (TPM2B_ENCRYPTED_SECRET); 329 TPM2B_UNMARSHAL(TPM2B_ENCRYPTED_SECRET, secret); 330 TPM2B_MARSHAL (TPM2B_PRIVATE_VENDOR_SPECIFIC); 331 TPM2B_UNMARSHAL(TPM2B_PRIVATE_VENDOR_SPECIFIC, buffer); 332 TPM2B_MARSHAL (TPM2B_PRIVATE); 333 TPM2B_UNMARSHAL(TPM2B_PRIVATE, buffer); 334 TPM2B_MARSHAL (TPM2B_ID_OBJECT); 335 TPM2B_UNMARSHAL(TPM2B_ID_OBJECT, credential); 336 TPM2B_MARSHAL (TPM2B_CONTEXT_SENSITIVE); 337 TPM2B_UNMARSHAL(TPM2B_CONTEXT_SENSITIVE, buffer); 338 TPM2B_MARSHAL (TPM2B_CONTEXT_DATA); 339 TPM2B_UNMARSHAL(TPM2B_CONTEXT_DATA, buffer); 340 TPM2B_MARSHAL (TPM2B_NONCE); 341 TPM2B_UNMARSHAL(TPM2B_NONCE, buffer); 342 TPM2B_MARSHAL (TPM2B_TIMEOUT); 343 TPM2B_UNMARSHAL(TPM2B_TIMEOUT, buffer); 344 TPM2B_MARSHAL (TPM2B_AUTH); 345 TPM2B_UNMARSHAL(TPM2B_AUTH, buffer); 346 TPM2B_MARSHAL (TPM2B_OPERAND); 347 TPM2B_UNMARSHAL(TPM2B_OPERAND, buffer); 348 TPM2B_MARSHAL (TPM2B_TEMPLATE); 349 TPM2B_UNMARSHAL(TPM2B_TEMPLATE, buffer); 350 TPM2B_MARSHAL_SUBTYPE(TPM2B_ECC_POINT, TPMS_ECC_POINT, point); 351 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_ECC_POINT, TPMS_ECC_POINT, point); 352 TPM2B_MARSHAL_SUBTYPE(TPM2B_NV_PUBLIC, TPMS_NV_PUBLIC, nvPublic); 353 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_NV_PUBLIC, TPMS_NV_PUBLIC, nvPublic); 354 TPM2B_MARSHAL_SUBTYPE(TPM2B_SENSITIVE, TPMT_SENSITIVE, sensitiveArea); 355 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_SENSITIVE, TPMT_SENSITIVE, sensitiveArea); 356 TPM2B_MARSHAL_SUBTYPE(TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE, sensitive); 357 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE, sensitive); 358 TPM2B_MARSHAL_SUBTYPE(TPM2B_CREATION_DATA, TPMS_CREATION_DATA, creationData); 359 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_CREATION_DATA, TPMS_CREATION_DATA, creationData); 360 TPM2B_MARSHAL_SUBTYPE(TPM2B_PUBLIC, TPMT_PUBLIC, publicArea); 361 TPM2B_UNMARSHAL_SUBTYPE(TPM2B_PUBLIC, TPMT_PUBLIC, publicArea); 362