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 "Commit_fp.h"
     10 #ifdef TPM_ALG_ECC
     11 //
     12 //
     13 //     Error Returns                     Meaning
     14 //
     15 //     TPM_RC_ATTRIBUTES                 keyHandle references a restricted key that is not a signing key
     16 //     TPM_RC_ECC_POINT                  either P1 or the point derived from s2 is not on the curve of
     17 //                                       keyHandle
     18 //     TPM_RC_HASH                       invalid name algorithm in keyHandle
     19 //     TPM_RC_KEY                        keyHandle does not reference an ECC key
     20 //     TPM_RC_SCHEME                     the scheme of keyHandle is not an anonymous scheme
     21 //     TPM_RC_NO_RESULT                  K, L or E was a point at infinity; or failed to generate r value
     22 //     TPM_RC_SIZE                       s2 is empty but y2 is not or s2 provided but y2 is not
     23 //
     24 TPM_RC
     25 TPM2_Commit(
     26    Commit_In         *in,                 // IN: input parameter list
     27    Commit_Out        *out                 // OUT: output parameter list
     28    )
     29 {
     30    OBJECT                    *eccKey;
     31    TPMS_ECC_POINT             P2;
     32    TPMS_ECC_POINT            *pP2 = NULL;
     33    TPMS_ECC_POINT            *pP1 = NULL;
     34    TPM2B_ECC_PARAMETER        r;
     35    TPM2B                     *p;
     36    TPM_RC                     result;
     37    TPMS_ECC_PARMS            *parms;
     38 
     39 // Input Validation
     40 
     41    eccKey = ObjectGet(in->signHandle);
     42    parms = & eccKey->publicArea.parameters.eccDetail;
     43 
     44    // Input key must be an ECC key
     45    if(eccKey->publicArea.type != TPM_ALG_ECC)
     46        return TPM_RC_KEY + RC_Commit_signHandle;
     47 
     48     // This command may only be used with a sign-only key using an anonymous
     49     // scheme.
     50     // NOTE: a sign + decrypt key has no scheme so it will not be an anonymous one
     51     // and an unrestricted sign key might no have a signing scheme but it can't
     52     // be use in Commit()
     53    if(!CryptIsSchemeAnonymous(parms->scheme.scheme))
     54             return TPM_RC_SCHEME + RC_Commit_signHandle;
     55 
     56    // Make sure that both parts of P2 are present if either is present
     57    if((in->s2.t.size == 0) != (in->y2.t.size == 0))
     58        return TPM_RC_SIZE + RC_Commit_y2;
     59 
     60    // Get prime modulus for the curve. This is needed later but getting this now
     61    // allows confirmation that the curve exists
     62    p = (TPM2B *)CryptEccGetParameter('p', parms->curveID);
     63 
     64    // if no p, then the curve ID is bad
     65 //
     66   // NOTE: This should never occur if the input unmarshaling code is working
     67   // correctly
     68   pAssert(p != NULL);
     69 
     70   // Get the random value that will be used in the point multiplications
     71   // Note: this does not commit the count.
     72   if(!CryptGenerateR(&r, NULL, parms->curveID, &eccKey->name))
     73       return TPM_RC_NO_RESULT;
     74 
     75   // Set up P2 if s2 and Y2 are provided
     76   if(in->s2.t.size != 0)
     77   {
     78       pP2 = &P2;
     79 
     80       // copy y2 for P2
     81       MemoryCopy2B(&P2.y.b, &in->y2.b, sizeof(P2.y.t.buffer));
     82       // Compute x2 HnameAlg(s2) mod p
     83 
     84       //      do the hash operation on s2 with the size of curve 'p'
     85       P2.x.t.size = CryptHashBlock(eccKey->publicArea.nameAlg,
     86                                    in->s2.t.size,
     87                                    in->s2.t.buffer,
     88                                    p->size,
     89                                    P2.x.t.buffer);
     90 
     91       // If there were error returns in the hash routine, indicate a problem
     92       // with the hash in
     93       if(P2.x.t.size == 0)
     94           return TPM_RC_HASH + RC_Commit_signHandle;
     95 
     96       // set p2.x = hash(s2) mod p
     97       if(CryptDivide(&P2.x.b, p, NULL, &P2.x.b) != TPM_RC_SUCCESS)
     98           return TPM_RC_NO_RESULT;
     99 
    100       if(!CryptEccIsPointOnCurve(parms->curveID, pP2))
    101           return TPM_RC_ECC_POINT + RC_Commit_s2;
    102 
    103       if(eccKey->attributes.publicOnly == SET)
    104           return TPM_RC_KEY + RC_Commit_signHandle;
    105 
    106   }
    107   // If there is a P1, make sure that it is on the curve
    108   // NOTE: an "empty" point has two UINT16 values which are the size values
    109   // for each of the coordinates.
    110   if(in->P1.t.size > 4)
    111   {
    112       pP1 = &in->P1.t.point;
    113       if(!CryptEccIsPointOnCurve(parms->curveID, pP1))
    114           return TPM_RC_ECC_POINT + RC_Commit_P1;
    115   }
    116 
    117   // Pass the parameters to CryptCommit.
    118   // The work is not done in-line because it does several point multiplies
    119   // with the same curve. There is significant optimization by not
    120   // having to reload the curve parameters multiple times.
    121   result = CryptCommitCompute(&out->K.t.point,
    122                               &out->L.t.point,
    123                               &out->E.t.point,
    124                               parms->curveID,
    125                               pP1,
    126                               pP2,
    127                               &eccKey->sensitive.sensitive.ecc,
    128                               &r);
    129   if(result != TPM_RC_SUCCESS)
    130       return result;
    131 
    132    out->K.t.size = TPMS_ECC_POINT_Marshal(&out->K.t.point, NULL, NULL);
    133    out->L.t.size = TPMS_ECC_POINT_Marshal(&out->L.t.point, NULL, NULL);
    134    out->E.t.size = TPMS_ECC_POINT_Marshal(&out->E.t.point, NULL, NULL);
    135 
    136    // The commit computation was successful so complete the commit by setting
    137    // the bit
    138    out->counter = CryptCommit();
    139 
    140    return TPM_RC_SUCCESS;
    141 }
    142 #endif
    143