ia64/xen-unstable

view tools/vtpm_manager/util/bsg.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 3233e7ecfa9f
children 06d84bf87159
line source
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 // ==================================================================
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"
49 static int g_log_recursion_level = 0;
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)
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)
64 // FIXME: trigger the selfcheck--need to use glibc hook to do this
65 //BOOL dummy1 = BSG_static_selfcheck();
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.
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.
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
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))
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)
105 // const with a compiler-computed size
106 #define FMT_SIZEOF(type) (__FMT_CONST | sizeof(type))
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))
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)
116 // 16-bit size followed by N key handles
117 #define FMT_SIZE16_HANDLES (__FMT_HSIZE | 2UL)
119 #define DIGEST_SIZE 20
120 typedef BSG_UINT32 BSG_HANDLE;
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;
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}},
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}},
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}},
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}},
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}},
193 {BSG_TPM_MIGRATIONKEYAUTH, "BSG_TPM_MIGRATIONKEYAUTH", {
194 BSG_TPM_PUBKEY,
195 BSG_TPM_MIGRATE_SCHEME,
196 BSG_TPM_DIGEST, 0}},
198 {BSG_TCPA_AUDIT_EVENT, "TCPA_AUDIT_EVENT", {
199 BSG_TPM_COMMAND_CODE,
200 BSG_TPM_RESULT, 0 }},
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}},
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} },
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} },
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}},
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}},
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}},
259 {BSG_TPM_PCRVALUE, "BSG_TPM_PCRVALUE", {FMT_DATA(DIGEST_SIZE), 0}},
261 {BSG_TCPA_PCR_FLAGS, "TCPA_PCR_FLAGS", {
262 FMT_U8,
263 FMT_U8,
264 0}},
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}},
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}},
284 {BSG_PACKED, "BSG_PACKED", {
285 __FMT_PACKED,
286 0 }},
288 {BSG_TYPE_MAX, "", {0}},
289 };
292 static const BSG_Format* find_format (BSG_Type t) {
293 BSG_Format * f = s_fmt;
295 if (t >= BSG_TYPE_MAX) {
296 return NULL;
297 }
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);
303 return f;
304 }
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;
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 }
334 bsglog ("%s\n", "BSG: static_selfcheck success!");
335 return TRUE;
336 }
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;
354 const BSG_BYTE* s = *src;
355 BSG_BYTE* d = dst;
357 BSG_UINT32 size = __FMT_MASK_SIZE(type);
358 BSG_UINT32 format = __FMT_MASK_FORMAT(type);
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);
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.
376 if (dst) {
377 bsglog ("BSG: __FMT_DATA size %d, src %p, dst %p\n", size, s, d);
378 memcpy(d, s, size);
379 }
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
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 }
392 if (dst)
393 BSG_PackConst(psize, size, d);
395 s += size;
396 d += size;
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*);
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);
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;
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 }
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[]
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 }
445 if (dst)
446 bsglog ("BSG_Pack type %s\n", x->name);
449 // iterate through the fields
450 const BSG_UINT32* f = x->fields;
451 for (; *f; f++) {
452 int fsize;
454 g_log_recursion_level++;
455 fsize = BSG_Pack_private((BSG_Type) *f, &s, dst ? d : NULL);
456 g_log_recursion_level--;
458 if (fsize <= 0)
459 return fsize;
461 d += fsize;
462 }
463 } else {
464 vtpmlogerror(VTPM_LOG_BSG, "BSG_Pack(): Unknown format %d\n", format);
465 return -1;
466 }
468 *src = s;
469 return (d - dst);
470 }
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;
486 const BSG_BYTE* s = src;
487 BSG_BYTE* d = dst ? *dst:NULL;
488 if (dst && !d)
489 dst = NULL;
491 BSG_UINT32 size = __FMT_MASK_SIZE(type);
492 BSG_UINT32 format = __FMT_MASK_FORMAT(type);
494 if (format == __FMT_CONST) {// We are dealing with a fixed length value ie. UINT32
496 BSG_UINT32 val = BSG_UnpackConst(s, size);
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 }
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);
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
516 BSG_UINT32 psize = BSG_UnpackConst(s, size);
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 }
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 }
532 s += size;
533 d += size;
535 BSG_BYTE* pdata = NULL;
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;
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;
565 d += sizeof(void*);
566 } else if (format == __FMT_PACKED) {
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");
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[]
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 }
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 }
591 if (dst)
592 *dst = d;
593 return (s - src);
594 }
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;
606 BSG_UINT32 size = __FMT_MASK_SIZE(type);
607 BSG_UINT32 format = __FMT_MASK_FORMAT(type);
609 if ((src == NULL) || (*src == NULL)) {
610 vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with NULL src\n");
611 return;
612 }
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 if (ptr)
620 free(ptr);
621 s += sizeof(void*);
622 } else if (format == __FMT_PACKED) {
624 // this doesn't make sense for unpacking, hence also for Destroy()
625 vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy() called with format __FMT_PACKED. "
626 "This does not make sense\n");
628 return;
629 } else if (format == 0) {
630 const BSG_Format* x = find_format (type);
631 if (x == NULL) {
632 vtpmlogerror(VTPM_LOG_BSG, "BSG_Destroy: cannot find type %d\n", type);
633 return;
634 }
636 const BSG_UINT32* f = x->fields;
637 for (; *f; f++)
638 BSG_Destroy_private((BSG_Type) *f, &s);
639 }
641 *src = s;
642 }
644 int BSG_Pack(BSG_Type type, const void* src, BSG_BYTE* dst)
645 {
646 const BSG_BYTE* src2 = (const BSG_BYTE*) src;
647 return BSG_Pack_private(type, &src2, dst);
648 }
650 int BSG_Unpack(BSG_Type type, const BSG_BYTE* src, void* dst)
651 {
652 BSG_BYTE* dst2 = (BSG_BYTE*) dst;
653 return BSG_Unpack_private(type, src, dst ? &dst2:NULL);
654 }
656 void BSG_Destroy(BSG_Type type, void* src)
657 {
658 BSG_BYTE* src2 = (BSG_BYTE*) src;
659 BSG_Destroy_private(type, &src2);
660 }
662 /**
663 * Pack a 8/16/32-bit constant into a buffer in big-endian format
664 * @val: constant value
665 * @size: constant size in bytes (1, 2, or 4)
666 * @dst: (OUT) buffer
667 */
668 void BSG_PackConst(BSG_UINT32 val, int size, BSG_BYTE* dst) {
669 bsglog ("BSG: PackConst on %d of size %i into address %p\n", val, size, dst);
671 switch (size) {
672 case 4:
673 dst[0] = (BSG_BYTE)((val >> 24) & 0xff);
674 dst[1] = (BSG_BYTE)((val >> 16) & 0xff);
675 dst[2] = (BSG_BYTE)((val >> 8) & 0xff);
676 dst[3] = (BSG_BYTE)(val & 0xff);
677 break;
678 case 2:
679 dst[0] = (BSG_BYTE)((val >> 8) & 0xff);
680 dst[1] = (BSG_BYTE)(val & 0xff);
681 break;
682 case 1:
683 dst[0] = (BSG_BYTE)(val & 0xff);
684 break;
685 }
686 }
688 /**
689 * Unpack a 8/16/32-bit constant from a buffer in big-endian format
690 * @src: buffer
691 * @size: constant size in bytes (1, 2, or 4)
692 */
693 BSG_UINT32 BSG_UnpackConst(const BSG_BYTE* src, int size) {
694 BSG_UINT32 val = 0;
696 if (src == NULL)
697 return 0;
699 switch (size) {
700 case 4:
701 val = (((BSG_UINT32) src[0]) << 24
702 | ((BSG_UINT32) src[1]) << 16
703 | ((BSG_UINT32) src[2]) << 8
704 | (BSG_UINT32) src[3]);
705 break;
706 case 2:
707 val = (((BSG_UINT32) src[0]) << 8 | (BSG_UINT32) src[1]);
708 break;
709 case 1:
710 val = (BSG_UINT32) src[0];
711 break;
712 }
713 return val;
714 }
716 // Pack a list of parameters. Beware not to send values, but rather you must
717 // send a pointer to your values Instead. This includes UINT32's.
718 int BSG_PackList( BSG_BYTE* dst, int ParamCount, ... ) {
719 int ParamNumber;
720 BSG_Type format;
721 BSG_BYTE* val = NULL;
722 int size=0;
724 va_list paramList;
725 va_start( paramList, ParamCount );
727 for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
728 //Strangeness with int is because gcc wanted an int rather than a enum of ints.
729 format = (BSG_Type) va_arg( paramList, int );
730 val = va_arg( paramList, BSG_BYTE* );
731 size += BSG_Pack(format, val, dst == NULL ? NULL : dst + size);
732 }
734 va_end (paramList);
736 return size;
737 }
739 // Unpack a list of parameters.
740 int BSG_UnpackList( const BSG_BYTE* src, int ParamCount, ... ) {
741 int ParamNumber = 0;
742 BSG_Type format;
743 BSG_BYTE* val = NULL;
744 int size = 0;
746 va_list paramList;
747 va_start( paramList, ParamCount );
749 for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
750 format = (BSG_Type) va_arg( paramList, int );
751 val = va_arg( paramList, BSG_BYTE* );
753 size += BSG_Unpack(format, src + size, val);
754 }
756 va_end( paramList );
758 return size;
759 }
761 // Destroy any memory allocated by calls to unpack
762 void BSG_DestroyList(int ParamCount, ... ) {
763 int ParamNumber = 0;
764 BSG_Type argType;
765 BSG_BYTE* paramValue = NULL;
767 va_list paramList;
768 va_start( paramList, ParamCount );
770 for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
771 argType = (BSG_Type) va_arg( paramList, int );
772 paramValue = va_arg( paramList, BSG_BYTE* );
774 BSG_Destroy(argType, paramValue);
775 }
777 va_end( paramList );
779 return;
780 }
783 // and a tuple version
784 TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]) {
785 int i;
787 for (i = 0; i < numParams; i++)
788 BSG_Destroy (params[i].type, params[i].addr);
790 return TPM_SUCCESS;
791 }
794 //
795 // wrappers of Pack and PackList which malloc the ouput buffer. to be freed
796 // by the caller later
797 //
799 int BSG_PackMalloc (BSG_Type type, const void* src, BSG_BYTE** o_dst) {
800 int size = BSG_Pack (type, src, NULL);
801 BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
802 if (dest == NULL)
803 return -1;
805 size = BSG_Pack(type, src, dest);
806 *o_dst = dest;
807 return size;
808 }
812 int BSG_PackListMalloc(BSG_BYTE** outBuffer, int ParamCount, ... ) {
813 va_list args;
814 int size;
816 va_start (args, ParamCount);
817 size = BSG_PackList (NULL, ParamCount, args);
818 va_end (args);
820 BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
821 if (dest == NULL)
822 return -1;
824 va_start (args, ParamCount);
825 size = BSG_PackList (dest, ParamCount, args);
826 va_end (args);
828 *outBuffer = dest;
829 return size;
830 }