/********************************************************************************/
/*										*/
/*			 Table Driven Marshal			    		*/
/*			     Written by Ken Goldman				*/
/*		       IBM Thomas J. Watson Research Center			*/
/*            $Id: TableDrivenMarshal.c 1628 2020-05-27 19:35:29Z kgoldman $	*/
/*										*/
/*  Licenses and Notices							*/
/*										*/
/*  1. Copyright Licenses:							*/
/*										*/
/*  - Trusted Computing Group (TCG) grants to the user of the source code in	*/
/*    this specification (the "Source Code") a worldwide, irrevocable, 		*/
/*    nonexclusive, royalty free, copyright license to reproduce, create 	*/
/*    derivative works, distribute, display and perform the Source Code and	*/
/*    derivative works thereof, and to grant others the rights granted herein.	*/
/*										*/
/*  - The TCG grants to the user of the other parts of the specification 	*/
/*    (other than the Source Code) the rights to reproduce, distribute, 	*/
/*    display, and perform the specification solely for the purpose of 		*/
/*    developing products based on such documents.				*/
/*										*/
/*  2. Source Code Distribution Conditions:					*/
/*										*/
/*  - Redistributions of Source Code must retain the above copyright licenses, 	*/
/*    this list of conditions and the following disclaimers.			*/
/*										*/
/*  - Redistributions in binary form must reproduce the above copyright 	*/
/*    licenses, this list of conditions	and the following disclaimers in the 	*/
/*    documentation and/or other materials provided with the distribution.	*/
/*										*/
/*  3. Disclaimers:								*/
/*										*/
/*  - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF	*/
/*  LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH	*/
/*  RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES)	*/
/*  THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE.		*/
/*  Contact TCG Administration (admin@trustedcomputinggroup.org) for 		*/
/*  information on specification licensing rights available through TCG 	*/
/*  membership agreements.							*/
/*										*/
/*  - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED 	*/
/*    WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR 	*/
/*    FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR 		*/
/*    NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY 		*/
/*    OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE.		*/
/*										*/
/*  - Without limitation, TCG and its members and licensors disclaim all 	*/
/*    liability, including liability for infringement of any proprietary 	*/
/*    rights, relating to use of information in this specification and to the	*/
/*    implementation of this specification, and TCG disclaims all liability for	*/
/*    cost of procurement of substitute goods or services, lost profits, loss 	*/
/*    of use, loss of data or any incidental, consequential, direct, indirect, 	*/
/*    or special damages, whether under contract, tort, warranty or otherwise, 	*/
/*    arising in any way out of use or reliance upon this specification or any 	*/
/*    information herein.							*/
/*										*/
/*  (c) Copyright IBM Corp. and others, 2016 - 2020				*/
/*										*/
/********************************************************************************/

/* 9.10.8.1	TableDrivenMarshal.c */

#include <assert.h>
#include "Tpm.h"
#include "Marshal.h"
#include "TableMarshal.h"
#if TABLE_DRIVEN_MARSHAL
extern ArrayMarshal_mst ArrayLookupTable[];

extern UINT16 MarshalLookupTable[];

typedef struct { int a; } External_Structure_t;

extern struct Exernal_Structure_t MarshalData;

#define IS_SUCCESS(UNMARSHAL_FUNCTION)				\
    (TPM_RC_SUCCESS == (result = (UNMARSHAL_FUNCTION)))
marshalIndex_t IntegerDispatch[] = {
    UINT8_MARSHAL_REF, UINT16_MARSHAL_REF, UINT32_MARSHAL_REF, UINT64_MARSHAL_REF,
    INT8_MARSHAL_REF,  INT16_MARSHAL_REF,  INT32_MARSHAL_REF,  INT64_MARSHAL_REF
};

#if 1
#define GetDescriptor(reference)					\
    ((MarshalHeader_mst *)(((BYTE *)(&MarshalData)) + (reference & NULL_MASK)))
#else
static const MarshalHeader_mst *GetDescriptor(marshalIndex_t index)
{
    const MarshalHeader_mst    *mst = MarshalLookupTable[index & NULL_MASK];
    return mst;
}
#endif
#define GetUnionDescriptor(_index_)				\
    ((UnionMarshal_mst *)GetDescriptor(_index_))
#define GetArrayDescriptor(_index_)					\
    ((ArrayMarshal_mst *))(ArrayLookupTable[_index_ & NULL_MASK])

//*** GetUnmarshaledInteger()
// Gets the unmarshaled value and normalizes it to a UIN32 for other
// processing (comparisons and such).
static UINT32 GetUnmarshaledInteger(
				    marshalIndex_t       type,
				    const void          *target
				    )
{
    int     size = (type & SIZE_MASK);
    //
    if(size == FOUR_BYTES)
	return *((UINT32 *)target);
    if(type & IS_SIGNED)
	{
	    if(size == TWO_BYTES)
		return (UINT32)*((int16_t *)target);
	    return (UINT32)*((int8_t *)target);
	}
    if(size == TWO_BYTES)
	return (UINT32)*((UINT16 *)target);
    return (UINT32)*((UINT8 *)target);
}
static UINT32 GetSelector(
			  void                *structure,
			  const UINT16        *values,
			  UINT16               descriptor
			  )
{
    unsigned            sel = GET_ELEMENT_NUMBER(descriptor);
    // Get the offset of the value in the unmarshaled structure
    const UINT16        *entry = &values[(sel * 3)];
    //
    return GetUnmarshaledInteger(GET_ELEMENT_SIZE(entry[0]),
				 ((UINT8 *)structure) + entry[2]);
}
static TPM_RC UnmarshalBytes(
			     UINT8               *target,        // IN/OUT: place to put the bytes
			     UINT8               **buffer,       // IN/OUT: source of the input data
			     *size,          // IN/OUT: remaining bytes in the input buffer
			     int                  count          // IN: number of bytes to get
			     )
{
    if((*size -= count) >= 0)
	{
	    memcpy(target, *buffer, count);
	    *buffer += count;
	    return TPM_RC_SUCCESS;
	}
    return TPM_RC_INSUFFICIENT;
}

/* 9.10.8.1.1.1	MarshalBytes() */
/* Marshal an array of bytes. */
static UINT16 MarshalBytes(
			   UINT8               *source,
			   UINT8               **buffer,
			   INT32               *size,
			   int32_t              count
			   )
{
    if(buffer != NULL)
	{
	    if(size != NULL && (size -= count) < 0)
		return 0;
	    memcpy(*buffer, source, count);
	    *buffer += count;
	}
    return (UINT16)count;
}
/* 9.10.8.1.1.2	ArrayUnmarshal() */
/* Unmarshal an array. The index is of the form: type_ARRAY_MARSHAL_INDEX. */
static TPM_RC ArrayUnmarshal(
			     UINT16               index,         // IN: the type of the array
			     UINT8               *target,        // IN: target for the data
			     UINT8               **buffer,       // IN/OUT: place to get the data
			     INT32               *size,          // IN/OUT: remaining unmarshal data
			     UINT32               count          // IN: number of values of 'index' to
			     //      unmarshal
			     )
{
    marshalIndex_t       which = ArrayLookupTable[index & NULL_MASK].type;
    UINT16               stride = ArrayLookupTable[index & NULL_MASK].stride;
    TPM_RC               result;
    //
    if(stride == 1) // A byte array
	result = UnmarshalBytes(target, buffer, size, count);
    else
	{
	    which |= index & NULL_FLAG;
	    for(result = TPM_RC_SUCCESS; count > 0; target += stride, count--)
		if(!IS_SUCCESS(Unmarshal(which, target, buffer, size)))
		    break;
	}
    return result;
}
/* 9.10.8.1.1.3	ArrayMarshal() */
static UINT16 ArrayMarshal(
			   UINT16               index,         // IN: the type of the array
			   UINT8               *source,        // IN: source of the data
			   UINT8               **buffer,       // IN/OUT: place to put the data
			   INT32               *size,          // IN/OUT: amount of space for the data
			   UINT32               count          // IN: number of values of 'index' to marshal
			   )
{
    marshalIndex_t      which = ArrayLookupTable[index & NULL_MASK].type;
    UINT16              stride = ArrayLookupTable[index & NULL_MASK].stride;
    UINT16              retVal;
    //
    if(stride == 1) // A byte array
	return MarshalBytes(source, buffer, size, count);
    which |= index & NULL_FLAG;
    for(retVal = 0
		 ; count > 0
     ; source += stride, count--)
	retVal += Marshal(which, source, buffer, size);
    
    return retVal;
}
/* 9.10.8.1.1.4	UnmarshalUnion() */
TPM_RC
UnmarshalUnion(
	       UINT16               typeIndex,         // IN: the thing to unmarshal
	       void                *target,            // IN: were the data goes to
	       UINT8               **buffer,           // IN/OUT: the data source buffer
	       INT32               *size,              // IN/OUT: the remaining size
	       UINT32               selector
	       )
{
    int                  i;
    UnionMarshal_mst    *ut = GetUnionDescriptor(typeIndex);
    marshalIndex_t       selected;
    //
    for(i = 0; i < ut->countOfselectors; i++)
	{
	    if(selector == ut->selectors[i])
		{
		    UINT8           *offset = ((UINT8 *)ut) + ut->offsetOfUnmarshalTypes;
		    // Get the selected thing to unmarshal
		    selected = ((marshalIndex_t *)offset)[i];
		    if(ut->modifiers & IS_ARRAY_UNION)
			return UnmarshalBytes(target, buffer, size, selected);
		    else
			{
			    // Propagate NULL_FLAG if the null flag was
			    // propagated to the structure containing the union
			    selected |= (typeIndex & NULL_FLAG);
			    return Unmarshal(selected, target, buffer, size);
			}
		}
	}
    // Didn't find the value.
    return TPM_RC_SELECTOR;
}
/* 9.10.8.1.1.5	MarshalUnion() */
UINT16
MarshalUnion(
	     UINT16               typeIndex,         // IN: the thing to marshal
	     void                *source,            // IN: were the data comes from
	     UINT8               **buffer,           // IN/OUT: the data source buffer
	     INT32               *size,              // IN/OUT: the remaining size
	     UINT32               selector           // IN: the union selector
	     )
{
    int                  i;
    UnionMarshal_mst    *ut = GetUnionDescriptor(typeIndex);
    marshalIndex_t       selected;
    //
    for(i = 0; i < ut->countOfselectors; i++)
	{
	    if(selector == ut->selectors[i])
		{
		    UINT8           *offset = ((UINT8 *)ut) + ut->offsetOfUnmarshalTypes;
		    // Get the selected thing to unmarshal
		    selected = ((marshalIndex_t *)offset)[i];
		    if(ut->modifiers & IS_ARRAY_UNION)
			return MarshalBytes(source, buffer, size, selected);
		    else
			return Marshal(selected, source, buffer, size);
		}
	}
    if(size != NULL)
	*size = -1;
    return 0;
}
TPM_RC
UnmarshalInteger(
		 int                  iSize,             // IN: Number of bytes in the integer
		 void                *target,            // OUT: receives the integer
		 UINT8               **buffer,           // IN/OUT: source of the data
		 INT32               *size,              // IN/OUT: amount of data available
		 UINT32              *value              // OUT: optional copy of 'target'
		 )
{
    // This is just to save typing
#define _MB_ (*buffer)
    // The size is a power of two so convert to regular integer
    int              bytes = (1 << (iSize & SIZE_MASK));
    //
    // Check to see if there is enough data to fulfill the request
    if((*size -= bytes) >= 0)
	{
	    // The most comon size
	    if(bytes == 4)
		{
		    *((UINT32 *)target) = (UINT32)((((((_MB_[0] << 8) | _MB_[1]) << 8)
						     | _MB_[2]) << 8) | _MB_[3]);
		    // If a copy is needed, copy it.
		    if(value != NULL)
			*value = *((UINT32 *)target);
		}
	    else if(bytes == 2)
		{
		    *((UINT16 *)target) = (UINT16)((_MB_[0] << 8) | _MB_[1]);
		    // If a copy is needed, copy with the appropriate sign extension
		    if(value != NULL)
			{
			    if(iSize & IS_SIGNED)
				*value = (UINT32)(*((INT16 *)target));
			    else
				*value = (UINT32)(*((UINT16 *)target));
			}
		}
	    else if(bytes == 1)
		{
		    *((UINT8*)target) = (UINT8)_MB_[0];
		    // If a copy is needed, copy with the appropriate sign extension
		    if(value != NULL)
			{
			    if(iSize & IS_SIGNED)
				*value = (UINT32)(*((INT8 *)target));
			    else
				*value = (UINT32)(*((UINT8 *)target));
			}
		}
	    else
		{
		    // There is no input type that is a 64-bit value other than a UINT64. So
		    // there is no reason to do anything other than unmarshal it.
		    *((UINT64 *)target) = BYTE_ARRAY_TO_UINT64(*buffer);
		}
	    *buffer += bytes;
	    return TPM_RC_SUCCESS;
#undef _MB_
	}
    return TPM_RC_INSUFFICIENT;
}
/* 9.10.8.1.1.6	Unmarshal() */
/* This is the function that performs unmarshaling of different numbered types. Each TPM type has a
   number. The number is used to lookup the address of the data structure that describes how to
   unmarshal that data type. */
TPM_RC
Unmarshal(
	  UINT16               typeIndex,         // IN: the thing to marshal
	  void                *target,            // IN: were the data goes from
	  UINT8               **buffer,           // IN/OUT: the data source buffer
	  INT32               *size               // IN/OUT: the remaining size
	  )
{
    const MarshalHeader_mst     *sel;
    TPM_RC                       result;
    //
    sel = GetDescriptor(typeIndex);
    switch(sel->marshalType)
	{
	  case UINT_MTYPE:
	      {
		  // A simple signed or unsigned integer value.
		  return UnmarshalInteger(sel->modifiers, target,
					  buffer, size, NULL);
	      }
	  case VALUES_MTYPE:
	      {
		  // This is the general-purpose structure that can handle things like
		  // TPMI_DH_PARENT that has multiple ranges, multiple singles and a
		  // 'null' value. When things cover a large range with holes in the range
		  // they can be turned into multiple ranges. There is no option for a bit
		  // field.
		  // The structure is:
		  //  typedef const struct ValuesMarshal_mst
		  //  {
		  //      UINT8           marshalType;        // VALUES_MTYPE
		  //      UINT8           modifiers;
		  //      UINT8           errorCode;
		  //      UINT8           singles;
		  //      UINT32          values[singles + 1 if TAKES_NULL];
		  //  } ValuesMarshal_mst;
		  // Unmarshal the base type
		  UINT32                   val;
		  if(IS_SUCCESS(UnmarshalInteger(sel->modifiers, target,
						 buffer, size, &val)))
		      {
			  ValuesMarshal_mst   *vmt = ((ValuesMarshal_mst *)sel);
			  const UINT32        *check = vmt->values;
			  //
			  // if the TAKES_NULL flag is set, then the first entry in the values
			  // list is the NULL value. Iy is not included in the 'ranges' or
			  // 'singles' count.
			  if((vmt->modifiers & TAKES_NULL) && (val == *check++))
			      {
				  if((typeIndex & NULL_FLAG) == 0)
				      result = (TPM_RC)(sel->errorCode);
			      }
			  // No NULL value or input is not the NULL value
			  else
			      {
				  int               i;
				  //
				  // Check all the min-max ranges.
				  for(i = vmt->ranges - 1; i >= 0; check = &check[2], i--)
				      if((UINT32)(val - check[0]) <= check[1])
					  break;
				  // if the input is in a selected range, then i >= 0
				  if(i < 0)
				      {
					  // Not in any range, so check sigles
					  for(i = vmt->singles - 1; i >= 0; i--)
					      if(val == check[i])
						  break;
				      }
				  // If input not in range and not in any single so return error
				  if(i < 0)
				      result = (TPM_RC)(sel->errorCode);
			      }
		      }
		  break;
	      }
	  case TABLE_MTYPE:
	      {
		  // This is a table with or without bit checking. The input is checked
		  // against each value in the table. If the value is in the table, and
		  // a bits table is present, then the bit field is checked to see if the
		  // indicated value is implemented. For example, if there is a table of
		  // allowed RSA key sizes and the 2nd entry matches, then the 2nd bit in
		  // thed bit field is checked to see if that allowed size is implemented in
		  // this TPM.
		  //  typedef const struct TableMarshal_mst
		  //  {
		  //      UINT8           marshalType;        // TABLE_MTYPE
		  //      UINT8           modifiers;
		  //      UINT8           errorCode;
		  //      UINT8           singles;
		  //      UINT32          values[singles + 1 if TAKES_NULL];
		  //  } TableMarshal_mst;
		  
		  UINT32                  val;
		  //
		  // Unmarshal the base type
		  if(IS_SUCCESS(UnmarshalInteger(sel->modifiers, target,
						 buffer, size, &val)))
		      {
			  TableMarshal_mst    *tmt = ((TableMarshal_mst *)sel);
			  const UINT32        *check = tmt->values;
			  //
			  // If this type has a null value, then it is the first value in the
			  // list of values. It does not count in the count of values
			  if((tmt->modifiers & TAKES_NULL) && (val == *check++))
			      {
				  if((typeIndex & NULL_FLAG) == 0)
				      result = (TPM_RC)(sel->errorCode);
			      }
			  else
			      {
				  int               i;
				  //
				  // Process the singles
				  for(i = tmt->singles - 1; i >= 0; i--)
				      {
					  // does the input value match the value in the table
					  if(val == check[i])
					      {
						  // If there is an associated bit table, make sure that
						  // the corresponding bit is SET
						  if((HAS_BITS & tmt->modifiers)
						     && (!IS_BIT_SET32(i, &(check[tmt->singles]))))
						      // if not SET, then this is a failure.
						      i = -1;
						  break;
					      }
				      }
				  // error if not found or bit not SET
				  if(i < 0)
				      result = (TPM_RC)(sel->errorCode);
			      }
		      }
		  break;
	      }
	  case MIN_MAX_MTYPE:
	      {
		  // A MIN_MAX is a range. It can have a bit field and a NULL value that is
		  // outside of the range. If the input value is in the min-max range then
		  // it is valid unless there is an associated bit field. Otherwise, it
		  // it is only valid if the corresponding value in the bit field is SET.
		  // The min value is 'values[0]' or 'values[1]' if there is a NULL value.
		  // The max value is the value after min. The max value is in the table as
		  // max minus min. This allows 'val' to be subtracted from min and then
		  // checked against max with one unsigned comparison. If present, the bit
		  // field will be the first 'values' after max.
		  //  typedef const struct MinMaxMarshal_mst
		  //  {
		  //      UINT8           marshalType;        // MIN_MAX_MTYPE
		  //      UINT8           modifiers;
		  //      UINT8           errorCode;
		  //      UINT32          values[2 + 1 if TAKES_NULL];
		  //  } MinMaxMarshal_mst;
		  UINT32               val;
		  //
		  // A min-max has a range. It can have a bit-field that is indexed to the
		  // min value (something that matches min has a bit at 0. This is useful
		  // for algorithms. The min-max define a range of algorithms to be checked
		  // and the bit field can check to see if the algorithm in that range is
		  // allowed.
		  if(IS_SUCCESS(UnmarshalInteger(sel->modifiers, target,
						 buffer, size, &val)))
		      {
			  MinMaxMarshal_mst   *mmt = (MinMaxMarshal_mst *)sel;
			  const UINT32        *check = mmt->values;
			  //
			  // If this type takes a NULL, see if it matches. This
			  if((mmt->modifiers & TAKES_NULL) && (val == *check++))
			      {
				  if((typeIndex & NULL_FLAG) == 0)
				      result = (TPM_RC)(mmt->errorCode);
			      }
			  else
			      {
				  val -= *check;
				  if((val > check[1])
				     || ((mmt->modifiers & HAS_BITS) &&
					 !IS_BIT_SET32(val, &check[2])))
				      result = (TPM_RC)(mmt->errorCode);
			      }
		      }
		  break;
	      }
	  case ATTRIBUTES_MTYPE:
	      {
		  //  This is used for TPMA values.
		  UINT32                   mask;
		  AttributesMarshal_mst   *amt = (AttributesMarshal_mst *)sel;
		  //
		  if(IS_SUCCESS(UnmarshalInteger(sel->modifiers, target,
						 buffer, size, &mask)))
		      {
			  if((mask & amt->attributeMask) != 0)
			      result = TPM_RC_RESERVED_BITS;
		      }
		  break;
	      }
	  case STRUCTURE_MTYPE:
	      {
		  // A structure (not a union). A structure has elements (one defined per
		  // row). Three UINT16 values are used for each row. The first indicates
		  // the type of the entry. They choices are: simple, union, or array. A
		  // simple type can be a simple integer or another structure. It can also
		  // be a specific "interface type." For example, when a structure entry is
		  // a value that is used define the dimension of an array, the entry of
		  // the structure will reference a "synthetic" interface type, most often
		  // a min-max value. If the type of the entry is union or array, then the
		  // first value indicates which of the previous elements provides the union
		  // selector or the array dimension. That previous entry is referenced in
		  // the unmarshaled structure in memory (Not the marshaled buffer). The
		  // previous entry indicates the location in the structure of the value.
		  // The second entry of each structure entry indicated the index of the
		  // type associated with the entry. This is an index into the array of
		  // arrays or the union table (merged with the normal table in this
		  // implementation). The final entry is the offset in the unmarshaled
		  // structure where the value is located. This is the offsetof(STRUcTURE,
		  // element). This value is added to the input 'target' or 'source' value
		  // to determine where the value goes.
		  StructMarshal_mst   *mst = (StructMarshal_mst *)sel;
		  int                  i;
		  const UINT16        *value = mst->values;
		  //
		  for(result = TPM_RC_SUCCESS, i = mst->elements
			       ; (TPM_RC_SUCCESS == result) && (i > 0)
		     ; value = &value[3], i--)
		      {
			  UINT16           descriptor = value[0];
			  marshalIndex_t   index = value[1];
			  // The offset of the object in the structure is in the last value in
			  // the triplet. Add that value to the start of the structure
			  UINT8           *offset = ((UINT8 *)target) + value[2];
			  //
			  if ((ELEMENT_PROPAGATE & descriptor)
			      && (typeIndex & NULL_FLAG))
			      index |= NULL_FLAG;
			  switch(GET_ELEMENT_TYPE(descriptor))
			      {
				case SIMPLE_STYPE:
				    {
					result = Unmarshal(index, offset, buffer, size);
					break;
				    }
				case UNION_STYPE:
				    {
					UINT32               choice;
					//
					// Get the selector or array dimension value
					choice = GetSelector(target, mst->values, descriptor);
					result = UnmarshalUnion(index, offset, buffer, size, choice);
					break;
				    }
				case ARRAY_STYPE:
				    {
					UINT32            dimension;
					//
					dimension = GetSelector(target, mst->values, descriptor);
					result = ArrayUnmarshal(index, offset, buffer,
								size, dimension);
					break;
				    }
				default:
				  result = TPM_RC_FAILURE;
				  break;
			      }
		      }
		  break;
	      }
	  case TPM2B_MTYPE:
	      {
		  // A primitive TPM2B. A size and byte buffer. The single value (other than
		  // the tag) references the synthetic 'interface' value for the size
		  // parameter.
		  Tpm2bMarshal_mst        *m2bt = (Tpm2bMarshal_mst *)sel;
		  //
		  if(IS_SUCCESS(Unmarshal(m2bt->sizeIndex, target, buffer, size)))
		      result = UnmarshalBytes(((TPM2B *)target)->buffer,
					      buffer, size, *((UINT16 *)target));
		  break;
	      }
	  case TPM2BS_MTYPE:
	      {
		  // This is used when a TPM2B contains a structure.
		  Tpm2bsMarshal_mst   *m2bst = (Tpm2bsMarshal_mst *)sel;
		  INT32          count;
		  //
		  if(IS_SUCCESS(Unmarshal(m2bst->sizeIndex, target, buffer, size)))
		      {
			  // fetch the size value and convert it to a 32-bit count value
			  count = (int32_t)*((UINT16 *)target);
			  if(count == 0)
			      {
				  if(m2bst->modifiers & SIZE_EQUAL)
				      result = TPM_RC_SIZE;
			      }
			  else if((*size -= count) >= 0)
			      {
				  marshalIndex_t  index = m2bst->dataIndex;
				  //
				  // If this type propigates a null (PROPIGATE_NULL), propigate it
				  if ((m2bst->modifiers & PROPAGATE_NULL)
				      && (typeIndex & typeIndex))
				      index |= NULL_FLAG;
				  // The structure might not start two bytes after the start of the
				  // size field. The offset to the start of the structure is between
				  // 2 and 8 bytes. This is encoded into the low 4 bits of the
				  // modifiers byte byte
				  if(IS_SUCCESS(Unmarshal(index,
							  ((UINT8 *)target) + (m2bst->modifiers & OFFSET_MASK),
							  buffer, &count)))
				      {
					  if(count != 0)
					      result = TPM_RC_SIZE;
				      }
			      }
			  else
			      result = TPM_RC_INSUFFICIENT;
		      }
		  break;
	      }
	  case LIST_MTYPE:
	      {
		  // Used for a list. A list is a qualified 32-bit 'count' value followed
		  // by a type indicator.
		  ListMarshal_mst     *mlt = (ListMarshal_mst *)sel;
		  marshalIndex_t      index = mlt->arrayRef;
		  //
		  if(IS_SUCCESS(Unmarshal(mlt->sizeIndex, target, buffer, size)))
		      {
			  // If this type propigates a null (PROPIGATE_NULL), propigate it
			  if ((mlt->modifiers & PROPAGATE_NULL)
			      && (typeIndex & NULL_FLAG))
			      index |= NULL_FLAG;
			  result = ArrayUnmarshal(index,
						  ((UINT8 *)target) +(mlt->modifiers & OFFSET_MASK),
						  buffer, size, *((UINT32 *)target));
		      }
		  break;
	      }
	  case NULL_MTYPE:
	      {
		  result = TPM_RC_SUCCESS;
		  break;
	      }
#if 0
	  case COMPOSITE_MTYPE:
	      {
		  CompositeMarshal_mst    *mct = (CompositeMarshal_mst *)sel;
		  int                      i;
		  UINT8                   *buf = *buffer;
		  INT32                   sz = *size;
		  //
		  result = TPM_RC_VALUE;
		  for(i = GET_ELEMENT_COUNT(mct->modifiers) - 1; i <= 0; i--)
		      {
			  marshalIndex_t      index = mct->types[i];
			  //
			  // This type might take a null so set it in each called value, just
			  // in case it is needed in that value. Only one value in each
			  // composite should have the takes null SET.
			  index |= typeIndex & NULL_MASK;
			  result = Unmarshal(index, target, buffer, size);
			  if(result == TPM_RC_SUCCESS)
			      break;
			  // Each of the composite values does its own unmarshaling. This
			  // has some execution overhead if it is unmarshaled multiple times
			  // but it saves code size in not having to reproduce the various
			  // unmarshaling types that can be in a composite. So, what this means
			  // is that the buffer pointer and size have to be reset for each
			  // unmarshaled value.
			  *buffer = buf;
			  *size = sz;
		      }
		  break;
	      }
#endof // 0
	  default:
	      {
		  result = TPM_RC_FAILURE;
		  break;
	      }
	}
    return result;
}
/* 9.10.8.1.1.7	Marshal() */
/* This is the function that drives marshaling of output. Because there is no validation of the
   output, there is a lot less code. */
UINT16 Marshal(
	       UINT16               typeIndex,         // IN: the thing to marshal
	       void                *source,            // IN: were the data comes from
	       UINT8               **buffer,           // IN/OUT: the data source buffer
	       INT32               *size               // IN/OUT: the remaining size
	       )
{
#define _source  ((UINT8 *)source)
    
    const MarshalHeader_mst     *sel;
    UINT16                       retVal;
    //
    sel = GetDescriptor(typeIndex);
    switch(sel->marshalType)
	{
	  case VALUES_MTYPE:
	  case UINT_MTYPE:
	  case TABLE_MTYPE:
	  case MIN_MAX_MTYPE:
	  case ATTRIBUTES_MTYPE:
	  case COMPOSITE_MTYPE:
	      {
#if BIG_ENDIAN_TPM
#define MM16    0
#define MM32    0
#define MM64    0
#else
		  // These flip the constant index values so that they count in reverse order when doing
		  // little-endian stuff
#define MM16    1
#define MM32    3
#define MM64    7
#endif
		  // Just change the name and cast the type of the input parameters for typing purposes
#define mb (*buffer)
#define _source ((UINT8 *)source)
		  retVal = (1 << (sel->modifiers & SIZE_MASK));
		  if(buffer != NULL)
		      {
			  if((size == NULL) || ((*size -= retVal) >= 0))
			      {
				  if(retVal == 4)
				      {
					  mb[0 ^ MM32] = _source[0];
					  mb[1 ^ MM32] = _source[1];
					  mb[2 ^ MM32] = _source[2];
					  mb[3 ^ MM32] = _source[3];
				      }
				  else if(retVal == 2)
				      {
					  mb[0 ^ MM16] = _source[0];
					  mb[1 ^ MM16] = _source[1];
				      }
				  else if(retVal == 1)
				      mb[0] = _source[0];
				  else
				      {
					  mb[0 ^ MM64] = _source[0];
					  mb[1 ^ MM64] = _source[1];
					  mb[2 ^ MM64] = _source[2];
					  mb[3 ^ MM64] = _source[3];
					  mb[4 ^ MM64] = _source[4];
					  mb[5 ^ MM64] = _source[5];
					  mb[6 ^ MM64] = _source[6];
					  mb[7 ^ MM64] = _source[7];
				      }
				  *buffer += retVal;
			      }
		      }
		  break;
	      }
	  case STRUCTURE_MTYPE:
	      {
		  //#define _mst  ((StructMarshal_mst *)sel)
		  StructMarshal_mst *mst = ((StructMarshal_mst *)sel);
		  int              i;
		  const UINT16  *value = mst->values;
		  
		  //
		  for(retVal = 0, i = mst->elements; i > 0; value = &value[3], i--)
		      {
			  UINT16           des = value[0];
			  marshalIndex_t   index = value[1];
			  UINT8           *offset = _source + value[2];
			  //
			  switch(GET_ELEMENT_TYPE(des))
			      {
				case UNION_STYPE:
				    {
					UINT32           choice;
					//
					choice = GetSelector(source, mst->values, des);
					retVal += MarshalUnion(index, offset, buffer, size, choice);
					break;
				    }
				case ARRAY_STYPE:
				    {
					UINT32               count;
					//
					count = GetSelector(source, mst->values, des);
					retVal += ArrayMarshal(index, offset, buffer, size, count);
					break;
				    }
				case SIMPLE_STYPE:
				default:
				    {
					// This is either another structure or a simple type
					retVal += Marshal(index, offset, buffer, size);
					break;
				    }
			      }
		      }
		  break;
	      }
	  case TPM2B_MTYPE:
	      {
		  // Get the number of bytes being marshaled
		  INT32         val = (int32_t)*((UINT16 *)source);
		  //
		  retVal = Marshal(UINT16_MARSHAL_REF, source, buffer, size);
		  
		  // This is a standard 2B with a byte buffer
		  retVal += MarshalBytes(((TPM2B *)_source)->buffer, buffer, size, val);
		  break;
	      }
	  case TPM2BS_MTYPE: // A structure in a TPM2B
	      {
		  Tpm2bsMarshal_mst       *m2bst = (Tpm2bsMarshal_mst *)sel;
		  UINT8                   *offset;
		  UINT16                   amount;
		  UINT8                   *marshaledSize;
		  //
		  // Save the address of where the size should go
		  marshaledSize = *buffer;
		  
		  // marshal the size (checks the space and advanced the pointer)
		  retVal = Marshal(UINT16_MARSHAL_REF, source, buffer, size);
		  
		  // This gets the offsetof the structure to marshal. It was placed in the
		  // modifiers byte because the offset from the start of the TPM2B to the
		  // start of the structure is going to be less than 8 and the modifiers
		  // byte isn't needed for anything else.
		  offset = _source + (m2bst->modifiers & SIGNED_MASK);
		  
		  // Marshal the structure and get its size
		  amount = Marshal(m2bst->dataIndex, offset, buffer, size);
		  
		  // put the size in the space used when the size was marshaled.
		  if(buffer != NULL)
		      UINT16_TO_BYTE_ARRAY(amount, marshaledSize);
		  retVal += amount;
		  break;
	      }
	  case LIST_MTYPE:
	      {
		  ListMarshal_mst *    mlt = ((ListMarshal_mst *)sel);
		  UINT8               *offset = _source + (mlt->modifiers & SIGNED_MASK);
		  retVal = Marshal(UINT32_MARSHAL_REF, source, buffer, size);
		  retVal += ArrayMarshal((marshalIndex_t)(mlt->arrayRef), offset,
					 buffer, size, *((UINT32 *)source));
		  break;
	      }
	  case NULL_MTYPE:
	    retVal = 0;
	    break;
	  case ERROR_MTYPE:
	  default:
	      {
		  if(size != NULL)
		      *size = -1;
		  retVal = 0;
		  break;
	      }
	}
    return retVal;
    
}
#endif // TABLE_DRIVEN_MARSHAL
