| /* Microsoft Reference Implementation for TPM 2.0 |
| * |
| * The copyright in this software is being made available under the BSD License, |
| * included below. This software may be subject to other third party and |
| * contributor rights, including patent rights, and no such rights are granted |
| * under this license. |
| * |
| * Copyright (c) Microsoft Corporation |
| * |
| * All rights reserved. |
| * |
| * BSD License |
| * |
| * Redistribution and use in source and binary forms, with or without modification, |
| * are permitted provided that the following conditions are met: |
| * |
| * Redistributions of source code must retain the above copyright notice, this list |
| * of conditions and the following disclaimer. |
| * |
| * Redistributions in binary form must reproduce the above copyright notice, this |
| * list of conditions and the following disclaimer in the documentation and/or |
| * other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS"" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #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 |
| INT32 *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; |
| } |
| |
| //*** 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; |
| } |
| |
| //*** 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; |
| } |
| |
| //*** 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; |
| } |
| |
| //***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; |
| } |
| |
| //*** 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; |
| } |
| |
| //*** 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 ranges; |
| // UINT8 singles; |
| // UINT32 values[1]; |
| // } 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 |
| // the 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; |
| } |
| #endif // 0 |
| default: |
| { |
| result = TPM_RC_FAILURE; |
| break; |
| } |
| } |
| return result; |
| } |
| |
| //*** 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 |