1 | // =================================================================== |
---|
2 | // |
---|
3 | // Copyright (c) 2005, Intel Corp. |
---|
4 | // All rights reserved. |
---|
5 | // |
---|
6 | // Redistribution and use in source and binary forms, with or without |
---|
7 | // modification, are permitted provided that the following conditions |
---|
8 | // are met: |
---|
9 | // |
---|
10 | // * Redistributions of source code must retain the above copyright |
---|
11 | // notice, this list of conditions and the following disclaimer. |
---|
12 | // * Redistributions in binary form must reproduce the above |
---|
13 | // copyright notice, this list of conditions and the following |
---|
14 | // disclaimer in the documentation and/or other materials provided |
---|
15 | // with the distribution. |
---|
16 | // * Neither the name of Intel Corporation nor the names of its |
---|
17 | // contributors may be used to endorse or promote products derived |
---|
18 | // from this software without specific prior written permission. |
---|
19 | // |
---|
20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
---|
21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
---|
22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
---|
23 | // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
---|
24 | // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
---|
25 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
---|
26 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
---|
27 | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
---|
28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
---|
29 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
---|
30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
---|
31 | // OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
32 | // =================================================================== |
---|
33 | // |
---|
34 | // bsg.cpp |
---|
35 | // |
---|
36 | // This file will handle all the TPM Byte Stream functions |
---|
37 | // |
---|
38 | // ================================================================== |
---|
39 | |
---|
40 | #include <stdio.h> |
---|
41 | #include <string.h> |
---|
42 | #include <stdarg.h> |
---|
43 | #include <malloc.h> |
---|
44 | #include "tcg.h" |
---|
45 | #include "crypto.h" |
---|
46 | #include "bsg.h" |
---|
47 | #include "log.h" |
---|
48 | |
---|
49 | static int g_log_recursion_level = 0; |
---|
50 | |
---|
51 | // a largest buffer size. if we get a buf size bigger than this when unpacking, |
---|
52 | // will complain! |
---|
53 | #define BSG_MAX_BUF_SIZE (1<<18) |
---|
54 | |
---|
55 | #define bsglog(fmt, ...) do { \ |
---|
56 | int __i; \ |
---|
57 | for (__i=0; __i < g_log_recursion_level; __i++) { \ |
---|
58 | vtpmloginfomore (VTPM_LOG_BSG, "%s", " "); \ |
---|
59 | } \ |
---|
60 | vtpmloginfomore (VTPM_LOG_BSG, fmt, __VA_ARGS__); \ |
---|
61 | } while (0) |
---|
62 | |
---|
63 | |
---|
64 | // FIXME: trigger the selfcheck--need to use glibc hook to do this |
---|
65 | //BOOL dummy1 = BSG_static_selfcheck(); |
---|
66 | |
---|
67 | |
---|
68 | // Interpretting Types |
---|
69 | // ------------------- |
---|
70 | // |
---|
71 | // Incoming Types are composed of two parts {format, info} squished into a |
---|
72 | // BSG_UINT32. The first 4 bits is a format spec indicating what type of |
---|
73 | // data it is. If the first 4 bits are zero the info corresponds to a value in |
---|
74 | // BSG_s_fmt[]. This is a structure whose composition is described in |
---|
75 | // BSG_s_fmt[]. If the value is non-zero, info corresponds to the size of the |
---|
76 | // data (in bytes) being passed in. For example a UINT32 being passed in would |
---|
77 | // have a format of (__FMT_CONST | 4). If both, the format and info are zero, |
---|
78 | // this is interpretted as the end of the structure, and the result is returned. |
---|
79 | |
---|
80 | // these flags are mutually exclusive, so I'll just make them |
---|
81 | // format values which indicate the semantics of the 'info' part and the source |
---|
82 | // data. The above description has been accordingly adjusted. |
---|
83 | |
---|
84 | // format values for determining what type of data the incoming type is |
---|
85 | // it's a 4 bit value, occupying the high 4 bits |
---|
86 | #define __FMT_CONST (1UL << 28) // Constant sized value |
---|
87 | #define __FMT_DATA (2UL << 28) // Believed to be raw data NOT {size,data} |
---|
88 | #define __FMT_SIZE (3UL << 28) // A size. Used in FMT_SIZE??_DATA. |
---|
89 | #define __FMT_HSIZE (4UL << 28) // A number of handles |
---|
90 | #define __FMT_PACKED (5UL << 28) // 'info' is unused; the source data consists |
---|
91 | // of {size32, data} but we're to pack only the |
---|
92 | // data as that is already packed, and so |
---|
93 | // can/must be unpacked without |
---|
94 | // explicitly reading it size |
---|
95 | |
---|
96 | #define __FMT_MASK 0x0FFFFFFFUL // this masks out the 4-bit format |
---|
97 | #define __FMT_MASK_SIZE(type) ((type) & __FMT_MASK) |
---|
98 | #define __FMT_MASK_FORMAT(type) ((type) & (~__FMT_MASK)) |
---|
99 | |
---|
100 | // constant (8/16/32-bits) |
---|
101 | #define FMT_U8 (__FMT_CONST | 1UL) |
---|
102 | #define FMT_U16 (__FMT_CONST | 2UL) |
---|
103 | #define FMT_U32 (__FMT_CONST | 4UL) |
---|
104 | |
---|
105 | // const with a compiler-computed size |
---|
106 | #define FMT_SIZEOF(type) (__FMT_CONST | sizeof(type)) |
---|
107 | |
---|
108 | // other data (size bytes) |
---|
109 | // Used primarily for DIGESTS -> FMT_DATA(20) |
---|
110 | #define FMT_DATA(size) (__FMT_DATA | ((BSG_UINT32) (size) & __FMT_MASK)) |
---|
111 | |
---|
112 | // 16/32-bit size followed by N bytes of data |
---|
113 | #define FMT_SIZE16_DATA (__FMT_SIZE | 2UL) |
---|
114 | #define FMT_SIZE32_DATA (__FMT_SIZE | 4UL) |
---|
115 | |
---|
116 | // 16-bit size followed by N key handles |
---|
117 | #define FMT_SIZE16_HANDLES (__FMT_HSIZE | 2UL) |
---|
118 | |
---|
119 | #define DIGEST_SIZE 20 |
---|
120 | typedef BSG_UINT32 BSG_HANDLE; |
---|
121 | |
---|
122 | // TCPA_AUTH has 11 fields! |
---|
123 | #define MAX_FIELDS 11 |
---|
124 | typedef struct BSG_Format |
---|
125 | { |
---|
126 | BSG_Type type; |
---|
127 | const char* name; |
---|
128 | BSG_UINT32 fields[MAX_FIELDS + 1]; |
---|
129 | } BSG_Format; |
---|
130 | |
---|
131 | /* |
---|
132 | * TCPA structure data formats |
---|
133 | */ |
---|
134 | // this has to be manually kept in sync with the |
---|
135 | // Type enum!! the static_selfcheck() function should be used regularly! |
---|
136 | static BSG_Format s_fmt[] = |
---|
137 | { |
---|
138 | {BSG_TYPE_UINT32, "BSG_TYPE_UINT32", {FMT_U32, 0}}, |
---|
139 | {BSG_TYPE_UINT16, "BSG_TYPE_UINT16", {FMT_U16, 0}}, |
---|
140 | {BSG_TYPE_BYTE, "BSG_TYPE_BYTE", {FMT_U8, 0}}, |
---|
141 | {BSG_TYPE_BOOL, "BSG_TYPE_BOOL", {FMT_U8, 0}}, |
---|
142 | {BSG_TPM_SIZE32_DATA, "BSG_TPM_SIZE32_DATA", {FMT_SIZE32_DATA, 0}}, |
---|
143 | {BSG_TPM_TAG, "BSG_TPM_TAG", {FMT_SIZEOF(TPM_TAG), 0}}, |
---|
144 | {BSG_TPM_HANDLE, "BSG_TPM_HANDLE", {FMT_SIZEOF(TPM_HANDLE), 0}}, |
---|
145 | {BSG_TPM_RESULT, "BSG_TPM_RESULT", {FMT_SIZEOF(TPM_RESULT), 0}}, |
---|
146 | {BSG_TPM_RESOURCE_TYPE, "BSG_TPM_RESOURCE_TYPE", {FMT_SIZEOF(TPM_RESOURCE_TYPE), 0}}, |
---|
147 | {BSG_TPM_COMMAND_CODE, "BSG_TPM_COMMAND_CODE", {FMT_U32, 0}}, |
---|
148 | {BSG_TPM_AUTH_DATA_USAGE, "BSG_TPM_AUTH_DATA_USAGE", {FMT_U8, 0}}, |
---|
149 | {BSG_TPM_ALGORITHM_ID, "BSG_TPM_ALGORITHM_ID", {FMT_U32, 0}}, |
---|
150 | {BSG_TPM_PROTOCOL_ID, "BSG_TPM_PROTOCOL_ID", {FMT_SIZEOF(TPM_PROTOCOL_ID), 0}}, |
---|
151 | {BSG_TPM_KEY_USAGE, "BSG_TPM_KEY_USAGE", {FMT_U16, 0}}, |
---|
152 | {BSG_TPM_ENC_SCHEME, "BSG_TPM_ENC_SCHEME", {FMT_U16, 0}}, |
---|
153 | {BSG_TPM_SIG_SCHEME, "BSG_TPM_SIG_SCHEME", {FMT_U16, 0}}, |
---|
154 | {BSG_TPM_MIGRATE_SCHEME, "BSG_TPM_MIGRATE_SCHEME", {FMT_U16, 0}}, |
---|
155 | {BSG_TPM_KEY_FLAGS, "BSG_TPM_KEY_FLAGS", {FMT_U32, 0}}, |
---|
156 | |
---|
157 | {BSG_TPM_AUTHDATA, "BSG_TPM_AUTHDATA", {FMT_DATA(DIGEST_SIZE), 0}}, |
---|
158 | {BSG_TPM_SECRET, "BSG_TPM_SECRET", {BSG_TPM_AUTHDATA, 0}}, |
---|
159 | {BSG_TPM_ENCAUTH, "BSG_TPM_ENCAUTH", {BSG_TPM_AUTHDATA, 0}}, |
---|
160 | {BSG_TPM_PAYLOAD_TYPE, "BSG_TPM_PAYLOAD_TYPE", {FMT_SIZEOF(TPM_PAYLOAD_TYPE), 0}}, |
---|
161 | |
---|
162 | {BSG_TPM_VERSION, "BSG_TPM_VERSION", {FMT_DATA(4), 0}}, // vers 1.2 |
---|
163 | {BSG_TPM_DIGEST, "BSG_TPM_DIGEST", {FMT_DATA(DIGEST_SIZE), 0}}, |
---|
164 | {BSG_TPM_COMPOSITE_HASH, "BSG_TPM_COMPOSITE_HASH", {BSG_TPM_DIGEST, 0}}, |
---|
165 | {BSG_TPM_CHOSENID_HASH, "BSG_TPM_CHOSENID_HASH", {BSG_TPM_DIGEST, 0}}, |
---|
166 | |
---|
167 | {BSG_TPM_NONCE, "BSG_TPM_NONCE", {FMT_DATA(DIGEST_SIZE), 0}}, |
---|
168 | {BSG_TPM_KEY_HANDLE, "BSG_TPM_KEY_HANDLE", {FMT_SIZEOF(TPM_KEY_HANDLE), 0}}, |
---|
169 | {BSG_TPM_KEY_HANDLE_LIST, "BSG_TPM_KEY_HANDLE_LIST", |
---|
170 | {FMT_SIZE16_HANDLES, 0}}, |
---|
171 | |
---|
172 | {BSG_TPM_KEY_PARMS, "BSG_TPM_KEY_PARMS", { |
---|
173 | BSG_TPM_ALGORITHM_ID, |
---|
174 | BSG_TPM_ENC_SCHEME, |
---|
175 | BSG_TPM_SIG_SCHEME, |
---|
176 | FMT_SIZE32_DATA, |
---|
177 | 0}}, |
---|
178 | {BSG_TPM_RSA_KEY_PARMS, "BSG_TPM_RSA_KEY_PARMS", { |
---|
179 | FMT_U32, FMT_U32, FMT_SIZE32_DATA, 0}}, |
---|
180 | {BSG_TPM_STORE_PUBKEY, "BSG_TPM_STORE_PUBKEY", {FMT_SIZE32_DATA, 0}}, |
---|
181 | {BSG_TPM_PUBKEY, "BSG_TPM_PUBKEY", {BSG_TPM_KEY_PARMS, BSG_TPM_STORE_PUBKEY, 0}}, |
---|
182 | {BSG_TPM_KEY, "BSG_TPM_KEY", { |
---|
183 | BSG_TPM_VERSION, |
---|
184 | BSG_TPM_KEY_USAGE, |
---|
185 | BSG_TPM_KEY_FLAGS, |
---|
186 | BSG_TPM_AUTH_DATA_USAGE, |
---|
187 | BSG_TPM_KEY_PARMS, |
---|
188 | FMT_SIZE32_DATA, // the PCR_INFO |
---|
189 | BSG_TPM_STORE_PUBKEY, |
---|
190 | FMT_SIZE32_DATA, // the encrypted part |
---|
191 | 0}}, |
---|
192 | |
---|
193 | {BSG_TPM_MIGRATIONKEYAUTH, "BSG_TPM_MIGRATIONKEYAUTH", { |
---|
194 | BSG_TPM_PUBKEY, |
---|
195 | BSG_TPM_MIGRATE_SCHEME, |
---|
196 | BSG_TPM_DIGEST, 0}}, |
---|
197 | |
---|
198 | {BSG_TCPA_AUDIT_EVENT, "TCPA_AUDIT_EVENT", { |
---|
199 | BSG_TPM_COMMAND_CODE, |
---|
200 | BSG_TPM_RESULT, 0 }}, |
---|
201 | |
---|
202 | {BSG_TCPA_EVENT_CERT, "TCPA_EVENT_CERT", { |
---|
203 | BSG_TPM_DIGEST, |
---|
204 | BSG_TPM_DIGEST, |
---|
205 | FMT_DATA(2), |
---|
206 | FMT_SIZE32_DATA, 0}}, |
---|
207 | |
---|
208 | {BSG_TPM_PCR_SELECTION, "BSG_TPM_PCR_SELECTION", {FMT_SIZE16_DATA, 0} }, |
---|
209 | {BSG_TPM_PCR_COMPOSITE, "BSG_TPM_PCR_COMPOSITE", { BSG_TPM_PCR_SELECTION, |
---|
210 | FMT_SIZE32_DATA, |
---|
211 | 0} }, |
---|
212 | |
---|
213 | {BSG_TPM_PCR_INFO, "BSG_TPM_PCR_INFO", { BSG_TPM_PCR_SELECTION, |
---|
214 | BSG_TPM_COMPOSITE_HASH, |
---|
215 | BSG_TPM_COMPOSITE_HASH, |
---|
216 | 0} }, |
---|
217 | |
---|
218 | |
---|
219 | {BSG_TPM_STORED_DATA, "BSG_TPM_STORED_DATA", { |
---|
220 | BSG_TPM_VERSION, |
---|
221 | FMT_SIZE32_DATA, |
---|
222 | FMT_SIZE32_DATA, |
---|
223 | 0}}, |
---|
224 | {BSG_TPM_SYMMETRIC_KEY, "BSG_TPM_SYMMETRIC_KEY", { |
---|
225 | BSG_TPM_ALGORITHM_ID, |
---|
226 | BSG_TPM_ENC_SCHEME, |
---|
227 | FMT_SIZE16_DATA, |
---|
228 | 0}}, |
---|
229 | {BSG_TPM_STORE_PRIVKEY, "BSG_TPM_STORE_PRIVKEY", {FMT_SIZE32_DATA, 0}}, |
---|
230 | {BSG_TPM_STORE_ASYMKEY, "BSG_TPM_STORE_ASYMKEY", { |
---|
231 | BSG_TPM_PAYLOAD_TYPE, |
---|
232 | BSG_TPM_SECRET, |
---|
233 | BSG_TPM_SECRET, |
---|
234 | BSG_TPM_DIGEST, |
---|
235 | BSG_TPM_STORE_PRIVKEY, |
---|
236 | 0}}, |
---|
237 | {BSG_TPM_MIGRATE_ASYMKEY, "BSG_TPM_MIGRATE_ASYMKEY", { |
---|
238 | BSG_TPM_PAYLOAD_TYPE, |
---|
239 | BSG_TPM_SECRET, |
---|
240 | BSG_TPM_DIGEST, |
---|
241 | FMT_U32, |
---|
242 | BSG_TPM_STORE_PRIVKEY, |
---|
243 | 0}}, |
---|
244 | |
---|
245 | {BSG_TPM_QUOTE_INFO, "BSG_TPM_QUOTE_INFO", { |
---|
246 | BSG_TPM_VERSION, |
---|
247 | FMT_DATA(4), |
---|
248 | BSG_TPM_COMPOSITE_HASH, |
---|
249 | BSG_TPM_NONCE, |
---|
250 | 0}}, |
---|
251 | |
---|
252 | {BSG_TPM_IDENTITY_CONTENTS, "BSG_TPM_IDENTITY_CONTENTS", { |
---|
253 | BSG_TPM_VERSION, |
---|
254 | FMT_U32, |
---|
255 | BSG_TPM_CHOSENID_HASH, |
---|
256 | BSG_TPM_PUBKEY, |
---|
257 | 0}}, |
---|
258 | |
---|
259 | {BSG_TPM_PCRVALUE, "BSG_TPM_PCRVALUE", {FMT_DATA(DIGEST_SIZE), 0}}, |
---|
260 | |
---|
261 | {BSG_TCPA_PCR_FLAGS, "TCPA_PCR_FLAGS", { |
---|
262 | FMT_U8, |
---|
263 | FMT_U8, |
---|
264 | 0}}, |
---|
265 | |
---|
266 | {BSG_TCS_AUTH, "TCS_AUTH", { |
---|
267 | BSG_TYPE_UINT32, |
---|
268 | BSG_TPM_NONCE, |
---|
269 | BSG_TPM_NONCE, |
---|
270 | BSG_TYPE_BOOL, |
---|
271 | BSG_TPM_AUTHDATA, |
---|
272 | 0}}, |
---|
273 | |
---|
274 | {BSG_TPM_KEY_NONSENSITIVE, "BSG_TPM_KEY_NONSENSITIVE", { |
---|
275 | BSG_TPM_VERSION, |
---|
276 | BSG_TPM_KEY_USAGE, |
---|
277 | BSG_TPM_KEY_FLAGS, |
---|
278 | BSG_TPM_AUTH_DATA_USAGE, |
---|
279 | BSG_TPM_KEY_PARMS, |
---|
280 | FMT_SIZE32_DATA, |
---|
281 | BSG_TPM_STORE_PUBKEY, |
---|
282 | 0}}, |
---|
283 | |
---|
284 | {BSG_PACKED, "BSG_PACKED", { |
---|
285 | __FMT_PACKED, |
---|
286 | 0 }}, |
---|
287 | |
---|
288 | {BSG_TYPE_MAX, "", {0}}, |
---|
289 | }; |
---|
290 | |
---|
291 | |
---|
292 | static const BSG_Format* find_format (BSG_Type t) { |
---|
293 | BSG_Format * f = s_fmt; |
---|
294 | |
---|
295 | if (t >= BSG_TYPE_MAX) { |
---|
296 | return NULL; |
---|
297 | } |
---|
298 | |
---|
299 | // WARNING: this depends on the enum and s_fmt[] array being in sync! make |
---|
300 | // sure to run the static_selfcheck() to make sure |
---|
301 | f = s_fmt + (t - BSG_TYPE_FIRST); |
---|
302 | |
---|
303 | return f; |
---|
304 | } |
---|
305 | |
---|
306 | // |
---|
307 | // a consistency-checking routine which can be run at compile time |
---|
308 | // (ie. immediately after compilation) |
---|
309 | // |
---|
310 | // tasks: |
---|
311 | // - verify that s_fmt has one entry per Type t, and that entry is at s_fmt[t] |
---|
312 | // |
---|
313 | // conditions: |
---|
314 | // - need that s_fmt[0] is the first type listed in the Type enum! ie the first |
---|
315 | // Type has value 0, not 1 |
---|
316 | // |
---|
317 | // FIXME: should have a function be passed in here which is called if the test |
---|
318 | // fails. Then the caller can decide what to do: abort, notify, whatever |
---|
319 | // |
---|
320 | BOOL BSG_static_selfcheck () |
---|
321 | { |
---|
322 | int i; |
---|
323 | |
---|
324 | for (i=BSG_TYPE_FIRST; i <= BSG_TYPE_MAX; i++) { |
---|
325 | if (s_fmt[i - BSG_TYPE_FIRST].type != i) { |
---|
326 | bsglog ("%s\n", "BSG: static_selfcheck failed!\n"); |
---|
327 | bsglog ("failure at %i, allegedly %s\n", |
---|
328 | i, s_fmt[i - BSG_TYPE_FIRST].name); |
---|
329 | abort(); |
---|
330 | return FALSE; |
---|
331 | } |
---|
332 | } |
---|
333 | |
---|
334 | bsglog ("%s\n", "BSG: static_selfcheck success!"); |
---|
335 | return TRUE; |
---|
336 | } |
---|
337 | |
---|
338 | |
---|
339 | /** |
---|
340 | * Flatten a TCPA structure into a buffer in big-endian format |
---|
341 | * @type: TCPA structure type |
---|
342 | * @src: (IN) TCPA structure (OUT) end of TCPA structure |
---|
343 | * @dst: (OUT) flattened data |
---|
344 | * Returns: Flattened size or -1 for unknown types |
---|
345 | */ |
---|
346 | // make it so that it can just run through the whole process and return |
---|
347 | // the packed size, without packing anything. this will be done if dst is NULL. |
---|
348 | static int BSG_Pack_private(BSG_Type type, const BSG_BYTE** src, BSG_BYTE* dst) |
---|
349 | { |
---|
350 | // check incoming parameters |
---|
351 | if (*src == NULL) |
---|
352 | return 0; |
---|
353 | |
---|
354 | const BSG_BYTE* s = *src; |
---|
355 | BSG_BYTE* d = dst; |
---|
356 | |
---|
357 | BSG_UINT32 size = __FMT_MASK_SIZE(type); |
---|
358 | BSG_UINT32 format = __FMT_MASK_FORMAT(type); |
---|
359 | |
---|
360 | if (format == __FMT_CONST) // We are dealing with a fixed length value eg. UINT32 |
---|
361 | { |
---|
362 | BSG_UINT32 val = 0; |
---|
363 | switch (size) { |
---|
364 | case 1: val = * (BYTE*) s; break; |
---|
365 | case 2: val = * (unsigned short*) s; break; |
---|
366 | case 4: val = * (BSG_UINT32*) s; break; |
---|
367 | } |
---|
368 | if (dst) |
---|
369 | BSG_PackConst(val, size, d); |
---|
370 | |
---|
371 | s += size; |
---|
372 | d += size; |
---|
373 | } else if (format == __FMT_DATA) { // We are dealing with raw data. Not sure when |
---|
374 | // this is used. |
---|
375 | |
---|
376 | if (dst) { |
---|
377 | bsglog ("BSG: __FMT_DATA size %d, src %p, dst %p\n", size, s, d); |
---|
378 | memcpy(d, s, size); |
---|
379 | } |
---|
380 | |
---|
381 | s += size; |
---|
382 | d += size; |
---|
383 | } else if (format == __FMT_SIZE || format == __FMT_HSIZE) { // It's a size, followed by that much data or handles |
---|
384 | |
---|
385 | BSG_UINT32 psize = 0; |
---|
386 | switch (size) { |
---|
387 | case 1: psize = * (BYTE*) s; break; |
---|
388 | case 2: psize = * (unsigned short*) s; break; |
---|
389 | case 4: psize = * (BSG_UINT32*) s; break; |
---|
390 | } |
---|
391 | |
---|
392 | if (dst) |
---|
393 | BSG_PackConst(psize, size, d); |
---|
394 | |
---|
395 | s += size; |
---|
396 | d += size; |
---|
397 | |
---|
398 | // now 's' points to an address, so cast it to BSG_BYTE** |
---|
399 | const BSG_BYTE* pdata = * ((BSG_BYTE**) s); |
---|
400 | s += sizeof(BSG_BYTE*); |
---|
401 | |
---|
402 | if (format == __FMT_HSIZE) {// This is a list of psize Handles |
---|
403 | if (dst) { |
---|
404 | BSG_HANDLE* d2 = (BSG_HANDLE*) d; |
---|
405 | BSG_HANDLE* p2 = (BSG_HANDLE*) pdata; |
---|
406 | BSG_UINT32 i; |
---|
407 | for (i = 0; i < psize; i++) |
---|
408 | d2[i] = BSG_UnpackConst((BSG_BYTE*)(p2 + i), 4); |
---|
409 | |
---|
410 | } |
---|
411 | d += psize * sizeof(BSG_HANDLE); |
---|
412 | } else {// If it's not psize handles, it's psize data. |
---|
413 | if (psize > 0) { |
---|
414 | if (dst) { |
---|
415 | bsglog ("BSG: __FMT_SIZE, size=%d, src=%p, dst=%p\n", |
---|
416 | psize, pdata, d); |
---|
417 | memcpy(d, pdata, psize); |
---|
418 | } |
---|
419 | } |
---|
420 | d += psize; |
---|
421 | } |
---|
422 | } else if (format == __FMT_PACKED) { |
---|
423 | // the source buffer is a pack_constbuf_t, which has a size and a |
---|
424 | // pointer. just copy the buffer value, the size is not included in the |
---|
425 | // output stream. |
---|
426 | pack_constbuf_t * buf = (pack_constbuf_t*) s; |
---|
427 | |
---|
428 | if (dst) { |
---|
429 | bsglog ("BSG: __FMT_PACKED, size=%d, src=%p, dst=%p\n", |
---|
430 | buf->size, buf->data, d); |
---|
431 | memcpy(d, buf->data, buf->size); |
---|
432 | } |
---|
433 | |
---|
434 | s += buf->size; |
---|
435 | d += buf->size; |
---|
436 | } else if (format == 0) {// No flags are set. This is a structure & it should |
---|
437 | // be looked up in the bsg_s_fmt[] |
---|
438 | |
---|
439 | const BSG_Format* x = find_format (type); |
---|
440 | if (x == NULL) { |
---|
441 | vtpmloginfo(VTPM_LOG_BSG, "BSG_Pack: cannot find type %d\n", type); |
---|
442 | return -1; |
---|
443 | } |
---|
444 | |
---|
445 | if (dst) |
---|
446 | bsglog ("BSG_Pack type %s\n", x->name); |
---|
447 | |
---|
448 | |
---|
449 | // iterate through the fields |
---|
450 | const BSG_UINT32* f = x->fields; |
---|
451 | for (; *f; f++) { |
---|
452 | int fsize; |
---|
453 | |
---|
454 | g_log_recursion_level++; |
---|
455 | fsize = BSG_Pack_private((BSG_Type) *f, &s, dst ? d : NULL); |
---|
456 | g_log_recursion_level--; |
---|
457 | |
---|
458 | if (fsize <= 0) |
---|
459 | return fsize; |
---|
460 | |
---|
461 | d += fsize; |
---|
462 | } |
---|
463 | } else { |
---|
464 | vtpmlogerror(VTPM_LOG_BSG, "BSG_Pack(): Unknown format %d\n", format); |
---|
465 | return -1; |
---|
466 | } |
---|
467 | |
---|
468 | *src = s; |
---|
469 | return (d - dst); |
---|
470 | } |
---|
471 | |
---|
472 | /** |
---|
473 | * Unflatten a TCPA structure from a buffer in big-endian format |
---|
474 | * @type: TCPA structure type |
---|
475 | * @src: flattened data |
---|
476 | * @dst: (IN) TCPA structure (OUT) end of TCPA structure |
---|
477 | * Returns: Flattened size |
---|
478 | * Note: Returns flattened size NOT the unpacked structure size |
---|
479 | */ |
---|
480 | static int BSG_Unpack_private(BSG_Type type, const BSG_BYTE* src, BSG_BYTE** dst) { |
---|
481 | // check incoming parameters |
---|
482 | if (src == NULL) |
---|
483 | return 0; |
---|
484 | |
---|
485 | |
---|
486 | const BSG_BYTE* s = src; |
---|
487 | BSG_BYTE* d = dst ? *dst:NULL; |
---|
488 | if (dst && !d) |
---|
489 | dst = NULL; |
---|
490 | |
---|
491 | BSG_UINT32 size = __FMT_MASK_SIZE(type); |
---|
492 | BSG_UINT32 format = __FMT_MASK_FORMAT(type); |
---|
493 | |
---|
494 | if (format == __FMT_CONST) {// We are dealing with a fixed length value ie. UINT32 |
---|
495 | |
---|
496 | BSG_UINT32 val = BSG_UnpackConst(s, size); |
---|
497 | |
---|
498 | if (dst) { |
---|
499 | switch (size) { |
---|
500 | case 1: *(BYTE *) d = (BSG_BYTE) val; break; |
---|
501 | case 2: *(unsigned short*) d = (unsigned short) val; break; |
---|
502 | case 4: *(BSG_UINT32*) d = (BSG_UINT32) val; break; |
---|
503 | } |
---|
504 | } |
---|
505 | |
---|
506 | s += size; |
---|
507 | d += size; |
---|
508 | } else if (format == __FMT_DATA) {// We are dealing with raw data. Not sure when this is used. |
---|
509 | if (dst) |
---|
510 | memcpy(d, s, size); |
---|
511 | |
---|
512 | d += size; |
---|
513 | s += size; |
---|
514 | } else if (format == __FMT_SIZE || format == __FMT_HSIZE) {// It's a size, followed by that much data or handles |
---|
515 | |
---|
516 | BSG_UINT32 psize = BSG_UnpackConst(s, size); |
---|
517 | |
---|
518 | if (psize > BSG_MAX_BUF_SIZE) { |
---|
519 | vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack runs into var-sized data bigger than %u bytes!!\n", |
---|
520 | BSG_MAX_BUF_SIZE); |
---|
521 | return -1; |
---|
522 | } |
---|
523 | |
---|
524 | if (dst) { |
---|
525 | switch (size) { |
---|
526 | case 1: *(BYTE *) d = (BSG_BYTE) psize; break; |
---|
527 | case 2: *(unsigned short*) d = (unsigned short) psize; break; |
---|
528 | case 4: *(BSG_UINT32*) d = (BSG_UINT32) psize; break; |
---|
529 | } |
---|
530 | } |
---|
531 | |
---|
532 | s += size; |
---|
533 | d += size; |
---|
534 | |
---|
535 | BSG_BYTE* pdata = NULL; |
---|
536 | |
---|
537 | if (psize) { |
---|
538 | if (format == __FMT_HSIZE) { // This is a list of psize Handles |
---|
539 | if (dst) { |
---|
540 | BSG_HANDLE* s2 = (BSG_HANDLE*) s; |
---|
541 | pdata = (BSG_BYTE *)malloc(psize * sizeof(BSG_HANDLE)); |
---|
542 | if (!pdata) |
---|
543 | return -1; |
---|
544 | |
---|
545 | BSG_HANDLE* p2 = (BSG_HANDLE*) pdata; |
---|
546 | BSG_UINT32 i; |
---|
547 | for (i = 0; i < psize; i++) { |
---|
548 | BSG_PackConst(s2[i], 4, (BSG_BYTE*)(p2 + i)); |
---|
549 | } |
---|
550 | } |
---|
551 | s += psize * sizeof(BSG_HANDLE); |
---|
552 | } else { // If it's not psize handles, it's psize data. |
---|
553 | if (dst) { |
---|
554 | pdata = (BSG_BYTE *)malloc(sizeof(BSG_BYTE) * psize); |
---|
555 | if (!pdata) |
---|
556 | return -1; |
---|
557 | memcpy(pdata, s, psize); |
---|
558 | } |
---|
559 | s += psize; |
---|
560 | } |
---|
561 | } |
---|
562 | if (dst) |
---|
563 | *(void**) d = pdata; |
---|
564 | |
---|
565 | d += sizeof(void*); |
---|
566 | } else if (format == __FMT_PACKED) { |
---|
567 | |
---|
568 | // this doesn't make sense for unpacking! |
---|
569 | vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack() called with format __FMT_PACKED. " |
---|
570 | "This does not make sense\n"); |
---|
571 | |
---|
572 | return -1; |
---|
573 | } else if (format == 0) {// No flags are set. This is a structure & it should |
---|
574 | // be looked up in the bsg_s_fmt[] |
---|
575 | |
---|
576 | const BSG_Format* x = find_format (type); |
---|
577 | if (x == NULL) { |
---|
578 | vtpmlogerror(VTPM_LOG_BSG, "BSG_Unpack: cannot find type %d\n", type); |
---|
579 | return -1; |
---|
580 | } |
---|
581 | |
---|
582 | const BSG_UINT32* f = x->fields; |
---|
583 | for (; *f; f++) { |
---|
584 | int fsize = BSG_Unpack_private((BSG_Type) *f, s, dst ? &d:NULL); |
---|
585 | if (fsize <= 0) |
---|
586 | return fsize; |
---|
587 | s += fsize; |
---|
588 | } |
---|
589 | } |
---|
590 | |
---|
591 | if (dst) |
---|
592 | *dst = d; |
---|
593 | return (s - src); |
---|
594 | } |
---|
595 | |
---|
596 | /** |
---|
597 | * Free memory associated with unpacked TCPA structure |
---|
598 | * @type: TCPA structure type |
---|
599 | * @src: (IN) TCPA structure (OUT) end of TCPA structure |
---|
600 | * Note: Destroy should be called on all structures created with Unpack |
---|
601 | * to ensure that any allocated memory is freed |
---|
602 | */ |
---|
603 | static void BSG_Destroy_private(BSG_Type type, BSG_BYTE** src) { |
---|
604 | BSG_BYTE* s = *src; |
---|
605 | |
---|
606 | BSG_UINT32 size = __FMT_MASK_SIZE(type); |
---|
607 | BSG_UINT32 format = __FMT_MASK_FORMAT(type); |
---|
608 | |
---|
609 | if ((src == NULL) || (*src == NULL)) { |
---|
610 | vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with NULL src\n"); |
---|
611 | return; |
---|
612 | } |
---|
613 | |
---|
614 | if (format == __FMT_CONST || format == __FMT_DATA) |
---|
615 | s += size; |
---|
616 | else if (format == __FMT_SIZE || format == __FMT_HSIZE) { |
---|
617 | s += size; |
---|
618 | BSG_BYTE* ptr = *(BSG_BYTE**) s; |
---|
619 | free(ptr); |
---|
620 | s += sizeof(void*); |
---|
621 | } else if (format == __FMT_PACKED) { |
---|
622 | |
---|
623 | // this doesn't make sense for unpacking, hence also for Destroy() |
---|
624 | vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with format __FMT_PACKED. " |
---|
625 | "This does not make sense\n"); |
---|
626 | |
---|
627 | return; |
---|
628 | } else if (format == 0) { |
---|
629 | const BSG_Format* x = find_format (type); |
---|
630 | if (x == NULL) { |
---|
631 | vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy: cannot find type %d\n", type); |
---|
632 | return; |
---|
633 | } |
---|
634 | |
---|
635 | const BSG_UINT32* f = x->fields; |
---|
636 | for (; *f; f++) |
---|
637 | BSG_Destroy_private((BSG_Type) *f, &s); |
---|
638 | } |
---|
639 | |
---|
640 | *src = s; |
---|
641 | } |
---|
642 | |
---|
643 | int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst) |
---|
644 | { |
---|
645 | const BSG_BYTE* src2 = (const BSG_BYTE*) src; |
---|
646 | return BSG_Pack_private(type, &src2, dst); |
---|
647 | } |
---|
648 | |
---|
649 | int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst) |
---|
650 | { |
---|
651 | BSG_BYTE* dst2 = (BSG_BYTE*) dst; |
---|
652 | return BSG_Unpack_private(type, src, dst ? &dst2:NULL); |
---|
653 | } |
---|
654 | |
---|
655 | void BSG_Destroy(BSG_Type type, void* src) |
---|
656 | { |
---|
657 | BSG_BYTE* src2 = (BSG_BYTE*) src; |
---|
658 | BSG_Destroy_private(type, &src2); |
---|
659 | } |
---|
660 | |
---|
661 | /** |
---|
662 | * Pack a 8/16/32-bit constant into a buffer in big-endian format |
---|
663 | * @val: constant value |
---|
664 | * @size: constant size in bytes (1, 2, or 4) |
---|
665 | * @dst: (OUT) buffer |
---|
666 | */ |
---|
667 | void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst) { |
---|
668 | bsglog ("BSG: PackConst on %d of size %i into address %p\n", val, size, dst); |
---|
669 | |
---|
670 | switch (size) { |
---|
671 | case 4: |
---|
672 | dst[0] = (BSG_BYTE)((val >> 24) & 0xff); |
---|
673 | dst[1] = (BSG_BYTE)((val >> 16) & 0xff); |
---|
674 | dst[2] = (BSG_BYTE)((val >> 8) & 0xff); |
---|
675 | dst[3] = (BSG_BYTE)(val & 0xff); |
---|
676 | break; |
---|
677 | case 2: |
---|
678 | dst[0] = (BSG_BYTE)((val >> 8) & 0xff); |
---|
679 | dst[1] = (BSG_BYTE)(val & 0xff); |
---|
680 | break; |
---|
681 | case 1: |
---|
682 | dst[0] = (BSG_BYTE)(val & 0xff); |
---|
683 | break; |
---|
684 | } |
---|
685 | } |
---|
686 | |
---|
687 | /** |
---|
688 | * Unpack a 8/16/32-bit constant from a buffer in big-endian format |
---|
689 | * @src: buffer |
---|
690 | * @size: constant size in bytes (1, 2, or 4) |
---|
691 | */ |
---|
692 | BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size) { |
---|
693 | BSG_UINT32 val = 0; |
---|
694 | |
---|
695 | if (src == NULL) |
---|
696 | return 0; |
---|
697 | |
---|
698 | switch (size) { |
---|
699 | case 4: |
---|
700 | val = (((BSG_UINT32) src[0]) << 24 |
---|
701 | | ((BSG_UINT32) src[1]) << 16 |
---|
702 | | ((BSG_UINT32) src[2]) << 8 |
---|
703 | | (BSG_UINT32) src[3]); |
---|
704 | break; |
---|
705 | case 2: |
---|
706 | val = (((BSG_UINT32) src[0]) << 8 | (BSG_UINT32) src[1]); |
---|
707 | break; |
---|
708 | case 1: |
---|
709 | val = (BSG_UINT32) src[0]; |
---|
710 | break; |
---|
711 | } |
---|
712 | return val; |
---|
713 | } |
---|
714 | |
---|
715 | // Pack a list of parameters. Beware not to send values, but rather you must |
---|
716 | // send a pointer to your values Instead. This includes UINT32's. |
---|
717 | int BSG_PackList( BSG_BYTE* dst, int ParamCount, ... ) { |
---|
718 | int ParamNumber; |
---|
719 | BSG_Type format; |
---|
720 | BSG_BYTE* val = NULL; |
---|
721 | int size=0; |
---|
722 | |
---|
723 | va_list paramList; |
---|
724 | va_start( paramList, ParamCount ); |
---|
725 | |
---|
726 | for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) { |
---|
727 | //Strangeness with int is because gcc wanted an int rather than a enum of ints. |
---|
728 | format = (BSG_Type) va_arg( paramList, int ); |
---|
729 | val = va_arg( paramList, BSG_BYTE* ); |
---|
730 | size += BSG_Pack(format, val, dst == NULL ? NULL : dst + size); |
---|
731 | } |
---|
732 | |
---|
733 | va_end (paramList); |
---|
734 | |
---|
735 | return size; |
---|
736 | } |
---|
737 | |
---|
738 | // Unpack a list of parameters. |
---|
739 | int BSG_UnpackList( const BSG_BYTE* src, int ParamCount, ... ) { |
---|
740 | int ParamNumber = 0; |
---|
741 | BSG_Type format; |
---|
742 | BSG_BYTE* val = NULL; |
---|
743 | int size = 0; |
---|
744 | |
---|
745 | va_list paramList; |
---|
746 | va_start( paramList, ParamCount ); |
---|
747 | |
---|
748 | for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) { |
---|
749 | format = (BSG_Type) va_arg( paramList, int ); |
---|
750 | val = va_arg( paramList, BSG_BYTE* ); |
---|
751 | |
---|
752 | size += BSG_Unpack(format, src + size, val); |
---|
753 | } |
---|
754 | |
---|
755 | va_end( paramList ); |
---|
756 | |
---|
757 | return size; |
---|
758 | } |
---|
759 | |
---|
760 | // Destroy any memory allocated by calls to unpack |
---|
761 | void BSG_DestroyList(int ParamCount, ... ) { |
---|
762 | int ParamNumber = 0; |
---|
763 | BSG_Type argType; |
---|
764 | BSG_BYTE* paramValue = NULL; |
---|
765 | |
---|
766 | va_list paramList; |
---|
767 | va_start( paramList, ParamCount ); |
---|
768 | |
---|
769 | for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) { |
---|
770 | argType = (BSG_Type) va_arg( paramList, int ); |
---|
771 | paramValue = va_arg( paramList, BSG_BYTE* ); |
---|
772 | |
---|
773 | BSG_Destroy(argType, paramValue); |
---|
774 | } |
---|
775 | |
---|
776 | va_end( paramList ); |
---|
777 | |
---|
778 | return; |
---|
779 | } |
---|
780 | |
---|
781 | |
---|
782 | // and a tuple version |
---|
783 | TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]) { |
---|
784 | int i; |
---|
785 | |
---|
786 | for (i = 0; i < numParams; i++) |
---|
787 | BSG_Destroy (params[i].type, params[i].addr); |
---|
788 | |
---|
789 | return TPM_SUCCESS; |
---|
790 | } |
---|
791 | |
---|
792 | |
---|
793 | // |
---|
794 | // wrappers of Pack and PackList which malloc the ouput buffer. to be freed |
---|
795 | // by the caller later |
---|
796 | // |
---|
797 | |
---|
798 | int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst) { |
---|
799 | int size = BSG_Pack (type, src, NULL); |
---|
800 | BSG_BYTE * dest = (BSG_BYTE*) malloc (size); |
---|
801 | if (dest == NULL) |
---|
802 | return -1; |
---|
803 | |
---|
804 | size = BSG_Pack(type, src, dest); |
---|
805 | *o_dst = dest; |
---|
806 | return size; |
---|
807 | } |
---|
808 | |
---|
809 | |
---|
810 | |
---|
811 | int BSG_PackListMalloc(BSG_BYTE** outBuffer, int ParamCount, ... ) { |
---|
812 | va_list args; |
---|
813 | int size; |
---|
814 | |
---|
815 | va_start (args, ParamCount); |
---|
816 | size = BSG_PackList (NULL, ParamCount, args); |
---|
817 | va_end (args); |
---|
818 | |
---|
819 | BSG_BYTE * dest = (BSG_BYTE*) malloc (size); |
---|
820 | if (dest == NULL) |
---|
821 | return -1; |
---|
822 | |
---|
823 | va_start (args, ParamCount); |
---|
824 | size = BSG_PackList (dest, ParamCount, args); |
---|
825 | va_end (args); |
---|
826 | |
---|
827 | *outBuffer = dest; |
---|
828 | return size; |
---|
829 | } |
---|