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 "Sign_fp.h"
     10 #include "Attest_spt_fp.h"
     11 //
     12 //
     13 //     Error Returns                     Meaning
     14 //
     15 //     TPM_RC_BINDING                    The public and private portions of the key are not properly bound.
     16 //     TPM_RC_KEY                        signHandle does not reference a signing key;
     17 //     TPM_RC_SCHEME                     the scheme is not compatible with sign key type, or input scheme is
     18 //                                       not compatible with default scheme, or the chosen scheme is not a
     19 //                                       valid sign scheme
     20 //     TPM_RC_TICKET                     validation is not a valid ticket
     21 //     TPM_RC_VALUE                      the value to sign is larger than allowed for the type of keyHandle
     22 //
     23 TPM_RC
     24 TPM2_Sign(
     25    Sign_In          *in,                   // IN: input parameter list
     26    Sign_Out         *out                   // OUT: output parameter list
     27    )
     28 {
     29    TPM_RC                     result;
     30    TPMT_TK_HASHCHECK          ticket;
     31    OBJECT                    *signKey;
     32 
     33 // Input Validation
     34    // Get sign key pointer
     35    signKey = ObjectGet(in->keyHandle);
     36 
     37    // pick a scheme for sign. If the input sign scheme is not compatible with
     38    // the default scheme, return an error.
     39    result = CryptSelectSignScheme(in->keyHandle, &in->inScheme);
     40    if(result != TPM_RC_SUCCESS)
     41    {
     42        if(result == TPM_RC_KEY)
     43            return TPM_RC_KEY + RC_Sign_keyHandle;
     44        else
     45            return RcSafeAddToResult(result, RC_Sign_inScheme);
     46    }
     47 
     48    // If validation is provided, or the key is restricted, check the ticket
     49    if(   in->validation.digest.t.size != 0
     50       || signKey->publicArea.objectAttributes.restricted == SET)
     51    {
     52        // Compute and compare ticket
     53        TicketComputeHashCheck(in->validation.hierarchy,
     54                               in->inScheme.details.any.hashAlg,
     55                               &in->digest, &ticket);
     56 
     57        if(!Memory2BEqual(&in->validation.digest.b, &ticket.digest.b))
     58            return TPM_RC_TICKET + RC_Sign_validation;
     59    }
     60    else
     61    // If we don't have a ticket, at least verify that the provided 'digest'
     62    // is the size of the scheme hashAlg digest.
     63    // NOTE: this does not guarantee that the 'digest' is actually produced using
     64    // the indicated hash algorithm, but at least it might be.
     65    {
     66        if(
     67 #if defined(SUPPORT_PADDING_ONLY_RSASSA) && SUPPORT_PADDING_ONLY_RSASSA == YES
     68            in->inScheme.details.any.hashAlg != TPM_ALG_NULL &&
     69 #endif
     70            in->digest.t.size
     71              != CryptGetHashDigestSize(in->inScheme.details.any.hashAlg))
     72              return TPM_RC_SIZE + RC_Sign_digest;
     73    }
     74 
     75 // Command Output
     76    // Sign the hash. A TPM_RC_VALUE or TPM_RC_SCHEME
     77    // error may be returned at this point
     78    result = CryptSign(in->keyHandle, &in->inScheme, &in->digest, &out->signature);
     79 
     80    return result;
     81 }
     82