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 "Policy_spt_fp.h"
     10 #include "PolicySigned_fp.h"
     11 //
     12 //
     13 //     Error Returns                     Meaning
     14 //
     15 //     TPM_RC_CPHASH                     cpHash was previously set to a different value
     16 //     TPM_RC_EXPIRED                    expiration indicates a time in the past or expiration is non-zero but no
     17 //                                       nonceTPM is present
     18 //     TPM_RC_HANDLE                     authObject need to have sensitive portion loaded
     19 //     TPM_RC_KEY                        authObject is not a signing scheme
     20 //     TPM_RC_NONCE                      nonceTPM is not the nonce associated with the policySession
     21 //     TPM_RC_SCHEME                     the signing scheme of auth is not supported by the TPM
     22 //     TPM_RC_SIGNATURE                  the signature is not genuine
     23 //     TPM_RC_SIZE                       input cpHash has wrong size
     24 //     TPM_RC_VALUE                      input policyID or expiration does not match the internal data in policy
     25 //                                       session
     26 //
     27 TPM_RC
     28 TPM2_PolicySigned(
     29    PolicySigned_In       *in,                  // IN: input parameter list
     30    PolicySigned_Out      *out                  // OUT: output parameter list
     31    )
     32 {
     33    TPM_RC                     result = TPM_RC_SUCCESS;
     34    SESSION                   *session;
     35    TPM2B_NAME                 entityName;
     36    TPM2B_DIGEST               authHash;
     37    HASH_STATE                 hashState;
     38    UINT32                     expiration = (in->expiration < 0)
     39                                            ? -(in->expiration) : in->expiration;
     40    UINT64                     authTimeout = 0;
     41 
     42 // Input Validation
     43 
     44    // Set up local pointers
     45    session = SessionGet(in->policySession);               // the session structure
     46 
     47    // Only do input validation if this is not a trial policy session
     48    if(session->attributes.isTrialPolicy == CLEAR)
     49    {
     50        if(expiration != 0)
     51            authTimeout = expiration * 1000 + session->startTime;
     52 
     53        result = PolicyParameterChecks(session, authTimeout,
     54                                        &in->cpHashA, &in->nonceTPM,
     55                                        RC_PolicySigned_nonceTPM,
     56                                        RC_PolicySigned_cpHashA,
     57                                        RC_PolicySigned_expiration);
     58        if(result != TPM_RC_SUCCESS)
     59            return result;
     60 
     61        // Re-compute the digest being signed
     62        /*(See part 3 specification)
     63        // The digest is computed as:
     64        //     aHash := hash ( nonceTPM | expiration | cpHashA | policyRef)
     65        // where:
     66        //      hash()      the hash associated with the signed auth
     67        //      nonceTPM    the nonceTPM value from the TPM2_StartAuthSession .
     68        //                  response If the authorization is not limited to this
     69        //                  session, the size of this value is zero.
     70        //      expiration time limit on authorization set by authorizing object.
     71        //                  This 32-bit value is set to zero if the expiration
     72        //                  time is not being set.
     73        //      cpHashA     hash of the command parameters for the command being
     74        //                  approved using the hash algorithm of the PSAP session.
     75        //                  Set to NULLauth if the authorization is not limited
     76        //                  to a specific command.
     77        //      policyRef   hash of an opaque value determined by the authorizing
     78        //                  object. Set to the NULLdigest if no hash is present.
     79        */
     80        // Start hash
     81        authHash.t.size = CryptStartHash(CryptGetSignHashAlg(&in->auth),
     82                                         &hashState);
     83 
     84        // add nonceTPM
     85        CryptUpdateDigest2B(&hashState, &in->nonceTPM.b);
     86 
     87        // add expiration
     88        CryptUpdateDigestInt(&hashState, sizeof(UINT32), (BYTE*) &in->expiration);
     89 
     90        // add cpHashA
     91        CryptUpdateDigest2B(&hashState, &in->cpHashA.b);
     92 
     93        // add policyRef
     94        CryptUpdateDigest2B(&hashState, &in->policyRef.b);
     95 
     96        // Complete digest
     97        CryptCompleteHash2B(&hashState, &authHash.b);
     98 
     99        // Validate Signature. A TPM_RC_SCHEME, TPM_RC_HANDLE or TPM_RC_SIGNATURE
    100        // error may be returned at this point
    101        result = CryptVerifySignature(in->authObject, &authHash, &in->auth);
    102        if(result != TPM_RC_SUCCESS)
    103            return RcSafeAddToResult(result, RC_PolicySigned_auth);
    104    }
    105 // Internal Data Update
    106    // Need the Name of the signing entity
    107    entityName.t.size = EntityGetName(in->authObject, &entityName.t.name);
    108 
    109    // Update policy with input policyRef and name of auth key
    110    // These values are updated even if the session is a trial session
    111    PolicyContextUpdate(TPM_CC_PolicySigned, &entityName, &in->policyRef,
    112                        &in->cpHashA, authTimeout, session);
    113 
    114 // Command Output
    115 
    116    // Create ticket and timeout buffer if in->expiration < 0 and this is not
    117    // a trial session.
    118    // NOTE: PolicyParameterChecks() makes sure that nonceTPM is present
    119    // when expiration is non-zero.
    120    if(   in->expiration < 0
    121       && session->attributes.isTrialPolicy == CLEAR
    122      )
    123    {
    124        // Generate timeout buffer. The format of output timeout buffer is
    125        // TPM-specific.
    126        // Note: can't do a direct copy because the output buffer is a byte
    127        // array and it may not be aligned to accept a 64-bit value. The method
    128        // used has the side-effect of making the returned value a big-endian,
    129        // 64-bit value that is byte aligned.
    130        out->timeout.t.size = sizeof(UINT64);
    131        UINT64_TO_BYTE_ARRAY(authTimeout, out->timeout.t.buffer);
    132 
    133        // Compute policy ticket
    134        TicketComputeAuth(TPM_ST_AUTH_SIGNED, EntityGetHierarchy(in->authObject),
    135                          authTimeout, &in->cpHashA, &in->policyRef, &entityName,
    136                          &out->policyTicket);
    137    }
    138    else
    139    {
    140        // Generate a null ticket.
    141        // timeout buffer is null
    142        out->timeout.t.size = 0;
    143 
    144        // auth ticket is null
    145        out->policyTicket.tag = TPM_ST_AUTH_SIGNED;
    146        out->policyTicket.hierarchy = TPM_RH_NULL;
    147        out->policyTicket.digest.t.size = 0;
    148    }
    149 
    150    return TPM_RC_SUCCESS;
    151 }
    152