source: trunk/packages/xen-3.1/xen-3.1/tools/vtpm_manager/util/bsg.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

  • Property svn:mime-type set to text/cpp
File size: 24.1 KB
Line 
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
49static 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
120typedef BSG_UINT32 BSG_HANDLE;
121
122// TCPA_AUTH has 11 fields!
123#define MAX_FIELDS 11
124typedef 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!
136static 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
292static 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//
320BOOL 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.
348static 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 */
480static 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 */
603static 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
643int 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
649int 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
655void 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 */
667void 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 */
692BSG_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.
717int 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.
739int 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
761void 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
783TPM_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
798int 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
811int 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}
Note: See TracBrowser for help on using the repository browser.