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/tss2_endian.h"
18 #define LOGMODULE marshal
19 #include "util/log.h"
20 
21 #define TPMA_MARSHAL(type) \
22 TSS2_RC Tss2_MU_##type##_Marshal(type src, uint8_t buffer[], \
23                                  size_t buffer_size, size_t *offset) \
24 { \
25     size_t  local_offset = 0; \
26 \
27     if (offset != NULL) { \
28         LOG_TRACE("offset non-NULL, initial value: %zu", *offset); \
29         local_offset = *offset; \
30     } \
31 \
32     if (buffer == NULL && offset == NULL) { \
33         LOG_ERROR("buffer and offset parameter are NULL"); \
34         return TSS2_MU_RC_BAD_REFERENCE; \
35     } else if (buffer == NULL && offset != NULL) { \
36         *offset += sizeof (src); \
37         LOG_TRACE("buffer NULL and offset non-NULL, updating offset to %zu", \
38              *offset); \
39         return TSS2_RC_SUCCESS; \
40     } else if (buffer_size < local_offset || \
41                buffer_size - local_offset < sizeof (src)) \
42     { \
43         LOG_WARNING(\
44              "buffer_size: %zu with offset: %zu are insufficient for object " \
45              "of size %zu", \
46              buffer_size, \
47              local_offset, \
48              sizeof (src)); \
49         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
50     } \
51 \
52     LOG_DEBUG(\
53          "Marshalling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \
54          " at index 0x%zx", \
55          (uintptr_t)&src, \
56          (uintptr_t)buffer, \
57          local_offset); \
58 \
59     switch (sizeof(src)) { \
60         case 1: \
61             break; \
62         case 2: \
63             src = HOST_TO_BE_16(src); \
64             break; \
65         case 4: \
66             src = HOST_TO_BE_32(src); \
67             break; \
68         case 8: \
69             src = HOST_TO_BE_64(src); \
70             break; \
71 \
72     } \
73     memcpy (&buffer [local_offset], &src, sizeof(src)); \
74     if (offset != NULL) { \
75         *offset = local_offset + sizeof (src); \
76         LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \
77     } \
78 \
79     return TSS2_RC_SUCCESS; \
80 }
81 
82 #define TPMA_UNMARSHAL(type) \
83 TSS2_RC Tss2_MU_##type##_Unmarshal(uint8_t const buffer[], size_t buffer_size, \
84                                    size_t *offset, type *dest) \
85 { \
86     size_t  local_offset = 0; \
87     type tmp = {0};\
88 \
89     if (offset != NULL) { \
90         LOG_TRACE("offset non-NULL, initial value: %zu", *offset); \
91         local_offset = *offset; \
92     } \
93 \
94     if (buffer == NULL || (dest == NULL && offset == NULL)) { \
95         LOG_ERROR("buffer or dest and offset parameter are NULL"); \
96         return TSS2_MU_RC_BAD_REFERENCE; \
97     } else if (dest == NULL && offset != NULL) { \
98         *offset += sizeof (type); \
99         LOG_TRACE(\
100              "buffer NULL and offset non-NULL, updating offset to %zu", \
101              *offset); \
102         return TSS2_RC_SUCCESS; \
103     } else if (buffer_size < local_offset || \
104                sizeof (*dest) > buffer_size - local_offset) \
105     { \
106         LOG_WARNING(\
107              "buffer_size: %zu with offset: %zu are insufficient for object " \
108              "of size %zu", \
109              buffer_size, \
110              local_offset, \
111              sizeof (*dest)); \
112         return TSS2_MU_RC_INSUFFICIENT_BUFFER; \
113     } \
114 \
115     LOG_DEBUG(\
116          "Unmarshaling " #type " from 0x%" PRIxPTR " to buffer 0x%" PRIxPTR \
117          " at index 0x%zx", \
118          (uintptr_t)buffer, \
119          (uintptr_t)dest, \
120          local_offset); \
121 \
122     memcpy (&tmp, &buffer [local_offset], sizeof (tmp)); \
123 \
124     switch (sizeof(tmp)) { \
125         case 1: \
126             *dest = tmp; \
127             break; \
128         case 2: \
129             *dest = BE_TO_HOST_16(tmp); \
130             break; \
131         case 4: \
132             *dest = BE_TO_HOST_32(tmp); \
133             break; \
134         case 8: \
135             *dest = BE_TO_HOST_64(tmp); \
136             break; \
137 \
138     } \
139 \
140     if (offset != NULL) { \
141         *offset = local_offset + sizeof (*dest); \
142         LOG_DEBUG("offset parameter non-NULL, updated to %zu", *offset); \
143     } \
144     return TSS2_RC_SUCCESS; \
145 }
146 
147 /*
148  * These macros expand to (un)marshal functions for each of the TPMA types
149  * the specification part 2.
150  */
151 TPMA_MARSHAL  (TPMA_ALGORITHM);
152 TPMA_UNMARSHAL(TPMA_ALGORITHM);
153 TPMA_MARSHAL  (TPMA_CC);
154 TPMA_UNMARSHAL(TPMA_CC);
155 TPMA_MARSHAL  (TPMA_LOCALITY);
156 TPMA_UNMARSHAL(TPMA_LOCALITY);
157 TPMA_MARSHAL  (TPMA_NV);
158 TPMA_UNMARSHAL(TPMA_NV);
159 TPMA_MARSHAL  (TPMA_OBJECT);
160 TPMA_UNMARSHAL(TPMA_OBJECT);
161 TPMA_MARSHAL  (TPMA_PERMANENT);
162 TPMA_UNMARSHAL(TPMA_PERMANENT);
163 TPMA_MARSHAL  (TPMA_SESSION);
164 TPMA_UNMARSHAL(TPMA_SESSION);
165 TPMA_MARSHAL  (TPMA_STARTUP_CLEAR);
166 TPMA_UNMARSHAL(TPMA_STARTUP_CLEAR);
167