Home | History | Annotate | Download | only in tpm2
      1 // This file was extracted from the TCG Published
      2 // Trusted Platform Module Library
      3 // Part 3: Commands
      4 // Family "2.0"
      5 // Level 00 Revision 01.16
      6 // October 30, 2014
      7 
      8 #include "InternalRoutines.h"
      9 #include "SequenceComplete_fp.h"
     10 #include "Platform.h"
     11 //
     12 //
     13 //     Error Returns               Meaning
     14 //
     15 //     TPM_RC_TYPE                 sequenceHandle does not reference a hash or HMAC sequence
     16 //                                 object
     17 //
     18 TPM_RC
     19 TPM2_SequenceComplete(
     20    SequenceComplete_In    *in,               // IN: input parameter list
     21    SequenceComplete_Out   *out               // OUT: output parameter list
     22    )
     23 {
     24    OBJECT                     *object;
     25 
     26 // Input validation
     27 
     28    // Get hash object pointer
     29    object = ObjectGet(in->sequenceHandle);
     30 
     31    // input handle must be a hash or HMAC sequence object.
     32    if(   object->attributes.hashSeq == CLEAR
     33       && object->attributes.hmacSeq == CLEAR)
     34        return TPM_RC_MODE + RC_SequenceComplete_sequenceHandle;
     35 
     36 // Command Output
     37 
     38    if(object->attributes.hashSeq == SET)           // sequence object for hash
     39    {
     40        // Update last piece of data
     41        HASH_OBJECT     *hashObject = (HASH_OBJECT *)object;
     42 
     43       // Get the hash algorithm before the algorithm is lost in CryptCompleteHash
     44        TPM_ALG_ID       hashAlg = hashObject->state.hashState[0].state.hashAlg;
     45 
     46        CryptUpdateDigest2B(&hashObject->state.hashState[0], &in->buffer.b);
     47 
     48        // Complete hash
     49        out->result.t.size
     50            = CryptGetHashDigestSize(
     51                  CryptGetContextAlg(&hashObject->state.hashState[0]));
     52 
     53        CryptCompleteHash2B(&hashObject->state.hashState[0], &out->result.b);
     54 
     55        // Check if the first block of the sequence has been received
     56        if(hashObject->attributes.firstBlock == CLEAR)
     57        {
     58            // If not, then this is the first block so see if it is 'safe'
     59            // to sign.
     60            if(TicketIsSafe(&in->buffer.b))
     61                hashObject->attributes.ticketSafe = SET;
     62        }
     63 
     64        // Output ticket
     65        out->validation.tag = TPM_ST_HASHCHECK;
     66        out->validation.hierarchy = in->hierarchy;
     67 
     68        if(in->hierarchy == TPM_RH_NULL)
     69        {
     70             // Ticket is not required
     71             out->validation.digest.t.size = 0;
     72        }
     73        else if(object->attributes.ticketSafe == CLEAR)
     74        {
     75            // Ticket is not safe to generate
     76            out->validation.hierarchy = TPM_RH_NULL;
     77            out->validation.digest.t.size = 0;
     78        }
     79        else
     80        {
     81            // Compute ticket
     82            TicketComputeHashCheck(out->validation.hierarchy, hashAlg,
     83                                   &out->result, &out->validation);
     84        }
     85    }
     86    else
     87    {
     88        HASH_OBJECT       *hashObject = (HASH_OBJECT *)object;
     89 
     90        //   Update last piece of data
     91        CryptUpdateDigest2B(&hashObject->state.hmacState, &in->buffer.b);
     92        // Complete hash/HMAC
     93        out->result.t.size =
     94            CryptGetHashDigestSize(
     95                CryptGetContextAlg(&hashObject->state.hmacState.hashState));
     96        CryptCompleteHMAC2B(&(hashObject->state.hmacState), &out->result.b);
     97 
     98        // No ticket is generated for HMAC sequence
     99        out->validation.tag = TPM_ST_HASHCHECK;
    100        out->validation.hierarchy = TPM_RH_NULL;
    101        out->validation.digest.t.size = 0;
    102    }
    103 
    104 // Internal Data Update
    105 
    106    // mark sequence object as evict so it will be flushed on the way out
    107    object->attributes.evict = SET;
    108 
    109    return TPM_RC_SUCCESS;
    110 }
    111