ia64/xen-unstable

view tools/vtpm_manager/util/bsg.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents fcb7e5616102
children
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 free(ptr);
620 s += sizeof(void*);
621 } else if (format == __FMT_PACKED) {
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");
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 }
635 const BSG_UINT32* f = x->fields;
636 for (; *f; f++)
637 BSG_Destroy_private((BSG_Type) *f, &s);
638 }
640 *src = s;
641 }
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 }
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 }
655 void BSG_Destroy(BSG_Type type, void* src)
656 {
657 BSG_BYTE* src2 = (BSG_BYTE*) src;
658 BSG_Destroy_private(type, &src2);
659 }
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);
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 }
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;
695 if (src == NULL)
696 return 0;
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 }
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;
723 va_list paramList;
724 va_start( paramList, ParamCount );
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 }
733 va_end (paramList);
735 return size;
736 }
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;
745 va_list paramList;
746 va_start( paramList, ParamCount );
748 for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
749 format = (BSG_Type) va_arg( paramList, int );
750 val = va_arg( paramList, BSG_BYTE* );
752 size += BSG_Unpack(format, src + size, val);
753 }
755 va_end( paramList );
757 return size;
758 }
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;
766 va_list paramList;
767 va_start( paramList, ParamCount );
769 for( ParamNumber = 1; ParamNumber <= ParamCount; ParamNumber++) {
770 argType = (BSG_Type) va_arg( paramList, int );
771 paramValue = va_arg( paramList, BSG_BYTE* );
773 BSG_Destroy(argType, paramValue);
774 }
776 va_end( paramList );
778 return;
779 }
782 // and a tuple version
783 TPM_RESULT BSG_DestroyTuple (int numParams, pack_tuple_t params[]) {
784 int i;
786 for (i = 0; i < numParams; i++)
787 BSG_Destroy (params[i].type, params[i].addr);
789 return TPM_SUCCESS;
790 }
793 //
794 // wrappers of Pack and PackList which malloc the ouput buffer. to be freed
795 // by the caller later
796 //
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;
804 size = BSG_Pack(type, src, dest);
805 *o_dst = dest;
806 return size;
807 }
811 int BSG_PackListMalloc(BSG_BYTE** outBuffer, int ParamCount, ... ) {
812 va_list args;
813 int size;
815 va_start (args, ParamCount);
816 size = BSG_PackList (NULL, ParamCount, args);
817 va_end (args);
819 BSG_BYTE * dest = (BSG_BYTE*) malloc (size);
820 if (dest == NULL)
821 return -1;
823 va_start (args, ParamCount);
824 size = BSG_PackList (dest, ParamCount, args);
825 va_end (args);
827 *outBuffer = dest;
828 return size;
829 }