Home | History | Annotate | Download | only in tpm2
      1 // This file was extracted from the TCG Published
      2 // Trusted Platform Module Library
      3 // Part 4: Supporting Routines
      4 // Family "2.0"
      5 // Level 00 Revision 01.16
      6 // October 30, 2014
      7 
      8 #include "InternalRoutines.h"
      9 #include "Attest_spt_fp.h"
     10 //
     11 //
     12 //          Functions
     13 //
     14 //          FillInAttestInfo()
     15 //
     16 //     Fill in common fields of TPMS_ATTEST structure.
     17 //
     18 //     Error Returns                     Meaning
     19 //
     20 //     TPM_RC_KEY                        key referenced by signHandle is not a signing key
     21 //     TPM_RC_SCHEME                     both scheme and key's default scheme are empty; or scheme is
     22 //                                       empty while key's default scheme requires explicit input scheme (split
     23 //                                       signing); or non-empty default key scheme differs from scheme
     24 //
     25 TPM_RC
     26 FillInAttestInfo(
     27      TPMI_DH_OBJECT         signHandle,            //   IN: handle of signing object
     28      TPMT_SIG_SCHEME       *scheme,                //   IN/OUT: scheme to be used for signing
     29      TPM2B_DATA            *data,                  //   IN: qualifying data
     30      TPMS_ATTEST           *attest                 //   OUT: attest structure
     31      )
     32 {
     33      TPM_RC                         result;
     34      TPMI_RH_HIERARCHY              signHierarhcy;
     35      result = CryptSelectSignScheme(signHandle, scheme);
     36      if(result != TPM_RC_SUCCESS)
     37          return result;
     38      // Magic number
     39      attest->magic = TPM_GENERATED_VALUE;
     40      if(signHandle == TPM_RH_NULL)
     41      {
     42          BYTE     *buffer;
     43          INT32     bufferSize;
     44          // For null sign handle, the QN is TPM_RH_NULL
     45          buffer = attest->qualifiedSigner.t.name;
     46          bufferSize = sizeof(TPM_HANDLE);
     47          attest->qualifiedSigner.t.size =
     48               TPM_HANDLE_Marshal(&signHandle, &buffer, &bufferSize);
     49      }
     50      else
     51      {
     52          // Certifying object qualified name
     53          // if the scheme is anonymous, this is an empty buffer
     54          if(CryptIsSchemeAnonymous(scheme->scheme))
     55               attest->qualifiedSigner.t.size = 0;
     56          else
     57               ObjectGetQualifiedName(signHandle, &attest->qualifiedSigner);
     58    }
     59    // current clock in plain text
     60    TimeFillInfo(&attest->clockInfo);
     61    // Firmware version in plain text
     62    attest->firmwareVersion = ((UINT64) gp.firmwareV1 << (sizeof(UINT32) * 8));
     63    attest->firmwareVersion += gp.firmwareV2;
     64    // Get the hierarchy of sign object. For NULL sign handle, the hierarchy
     65    // will be TPM_RH_NULL
     66    signHierarhcy = EntityGetHierarchy(signHandle);
     67    if(signHierarhcy != TPM_RH_PLATFORM && signHierarhcy != TPM_RH_ENDORSEMENT)
     68    {
     69        // For sign object is not in platform or endorsement hierarchy,
     70        // obfuscate the clock and firmwereVersion information
     71        UINT64          obfuscation[2];
     72        TPMI_ALG_HASH   hashAlg;
     73          // Get hash algorithm
     74          if(signHandle == TPM_RH_NULL || signHandle == TPM_RH_OWNER)
     75          {
     76               hashAlg = CONTEXT_INTEGRITY_HASH_ALG;
     77          }
     78          else
     79          {
     80               OBJECT          *signObject = NULL;
     81               signObject = ObjectGet(signHandle);
     82               hashAlg = signObject->publicArea.nameAlg;
     83          }
     84          KDFa(hashAlg, &gp.shProof.b, "OBFUSCATE",
     85                &attest->qualifiedSigner.b, NULL, 128, (BYTE *)&obfuscation[0], NULL);
     86          // Obfuscate data
     87          attest->firmwareVersion += obfuscation[0];
     88          attest->clockInfo.resetCount += (UINT32)(obfuscation[1] >> 32);
     89          attest->clockInfo.restartCount += (UINT32)obfuscation[1];
     90    }
     91    // External data
     92    if(CryptIsSchemeAnonymous(scheme->scheme))
     93        attest->extraData.t.size = 0;
     94    else
     95    {
     96        // If we move the data to the attestation structure, then we will not use
     97        // it in the signing operation except as part of the signed data
     98        attest->extraData = *data;
     99        data->t.size = 0;
    100    }
    101    return TPM_RC_SUCCESS;
    102 }
    103 //
    104 //
    105 //          SignAttestInfo()
    106 //
    107 //     Sign a TPMS_ATTEST structure. If signHandle is TPM_RH_NULL, a null signature is returned.
    108 //
    109 //
    110 //
    111 //
    112 //      Error Returns                     Meaning
    113 //
    114 //      TPM_RC_ATTRIBUTES                 signHandle references not a signing key
    115 //      TPM_RC_SCHEME                     scheme is not compatible with signHandle type
    116 //      TPM_RC_VALUE                      digest generated for the given scheme is greater than the modulus of
    117 //                                        signHandle (for an RSA key); invalid commit status or failed to
    118 //                                        generate r value (for an ECC key)
    119 //
    120 TPM_RC
    121 SignAttestInfo(
    122    TPMI_DH_OBJECT           signHandle,                //   IN: handle of sign object
    123    TPMT_SIG_SCHEME         *scheme,                    //   IN: sign scheme
    124    TPMS_ATTEST             *certifyInfo,               //   IN: the data to be signed
    125    TPM2B_DATA              *qualifyingData,            //   IN: extra data for the signing proce
    126    TPM2B_ATTEST            *attest,                    //   OUT: marshaled attest blob to be
    127                                                        //       signed
    128    TPMT_SIGNATURE          *signature                  //   OUT: signature
    129    )
    130 {
    131    TPM_RC                         result;
    132    TPMI_ALG_HASH                  hashAlg;
    133    BYTE                           *buffer;
    134    INT32                          bufferSize;
    135    HASH_STATE                     hashState;
    136    TPM2B_DIGEST                   digest;
    137    // Marshal TPMS_ATTEST structure for hash
    138    buffer = attest->t.attestationData;
    139    bufferSize = sizeof(TPMS_ATTEST);
    140    attest->t.size = TPMS_ATTEST_Marshal(certifyInfo, &buffer, &bufferSize);
    141    if(signHandle == TPM_RH_NULL)
    142    {
    143        signature->sigAlg = TPM_ALG_NULL;
    144    }
    145    else
    146    {
    147        // Attestation command may cause the orderlyState to be cleared due to
    148        // the reporting of clock info. If this is the case, check if NV is
    149        // available first
    150        if(gp.orderlyState != SHUTDOWN_NONE)
    151        {
    152            // The command needs NV update. Check if NV is available.
    153            // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
    154            // this point
    155            result = NvIsAvailable();
    156            if(result != TPM_RC_SUCCESS)
    157                return result;
    158        }
    159          // Compute hash
    160          hashAlg = scheme->details.any.hashAlg;
    161          digest.t.size = CryptStartHash(hashAlg, &hashState);
    162          CryptUpdateDigest(&hashState, attest->t.size, attest->t.attestationData);
    163          CryptCompleteHash2B(&hashState, &digest.b);
    164          // If there is qualifying data, need to rehash the the data
    165          // hash(qualifyingData || hash(attestationData))
    166          if(qualifyingData->t.size != 0)
    167          {
    168              CryptStartHash(hashAlg, &hashState);
    169              CryptUpdateDigest(&hashState,
    170                                qualifyingData->t.size,
    171                                qualifyingData->t.buffer);
    172              CryptUpdateDigest(&hashState, digest.t.size, digest.t.buffer);
    173              CryptCompleteHash2B(&hashState, &digest.b);
    174           }
    175           // Sign the hash. A TPM_RC_VALUE, TPM_RC_SCHEME, or
    176           // TPM_RC_ATTRIBUTES error may be returned at this point
    177           return CryptSign(signHandle,
    178                            scheme,
    179                            &digest,
    180                            signature);
    181      }
    182      return TPM_RC_SUCCESS;
    183 }
    184