15679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// This file was extracted from the TCG Published
25679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Trusted Platform Module Library
35679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Part 3: Commands
45679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Family "2.0"
55679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Level 00 Revision 01.16
65679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// October 30, 2014
75679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
85679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#include "InternalRoutines.h"
95679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#include "Commit_fp.h"
105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#ifdef TPM_ALG_ECC
115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     Error Returns                     Meaning
145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_ATTRIBUTES                 keyHandle references a restricted key that is not a signing key
165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_ECC_POINT                  either P1 or the point derived from s2 is not on the curve of
175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//                                       keyHandle
185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_HASH                       invalid name algorithm in keyHandle
195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_KEY                        keyHandle does not reference an ECC key
205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_SCHEME                     the scheme of keyHandle is not an anonymous scheme
215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_NO_RESULT                  K, L or E was a point at infinity; or failed to generate r value
225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//     TPM_RC_SIZE                       s2 is empty but y2 is not or s2 provided but y2 is not
235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
245679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM_RC
255679752bf24c21135884e987c4077e2f7184897Vadim BendeburyTPM2_Commit(
265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   Commit_In         *in,                 // IN: input parameter list
275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   Commit_Out        *out                 // OUT: output parameter list
285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   )
295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury{
305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   OBJECT                    *eccKey;
315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT             P2;
325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT            *pP2 = NULL;
335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_POINT            *pP1 = NULL;
345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B_ECC_PARAMETER        r;
355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM2B                     *p;
365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPM_RC                     result;
375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   TPMS_ECC_PARMS            *parms;
385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury// Input Validation
405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   eccKey = ObjectGet(in->signHandle);
425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   parms = & eccKey->publicArea.parameters.eccDetail;
435679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
445679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Input key must be an ECC key
455679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(eccKey->publicArea.type != TPM_ALG_ECC)
465679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return TPM_RC_KEY + RC_Commit_signHandle;
475679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
485679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // This command may only be used with a sign-only key using an anonymous
495679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // scheme.
505679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // NOTE: a sign + decrypt key has no scheme so it will not be an anonymous one
515679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // and an unrestricted sign key might no have a signing scheme but it can't
525679752bf24c21135884e987c4077e2f7184897Vadim Bendebury    // be use in Commit()
535679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if(!CryptIsSchemeAnonymous(parms->scheme.scheme))
545679752bf24c21135884e987c4077e2f7184897Vadim Bendebury            return TPM_RC_SCHEME + RC_Commit_signHandle;
555679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
565679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Make sure that both parts of P2 are present if either is present
575679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   if((in->s2.t.size == 0) != (in->y2.t.size == 0))
585679752bf24c21135884e987c4077e2f7184897Vadim Bendebury       return TPM_RC_SIZE + RC_Commit_y2;
595679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
605679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // Get prime modulus for the curve. This is needed later but getting this now
615679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // allows confirmation that the curve exists
625679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   p = (TPM2B *)CryptEccGetParameter('p', parms->curveID);
635679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
645679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // if no p, then the curve ID is bad
655679752bf24c21135884e987c4077e2f7184897Vadim Bendebury//
665679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // NOTE: This should never occur if the input unmarshaling code is working
675679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // correctly
685679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  pAssert(p != NULL);
695679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
705679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // Get the random value that will be used in the point multiplications
715679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // Note: this does not commit the count.
725679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  if(!CryptGenerateR(&r, NULL, parms->curveID, &eccKey->name))
735679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      return TPM_RC_NO_RESULT;
745679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
755679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // Set up P2 if s2 and Y2 are provided
765679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  if(in->s2.t.size != 0)
775679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  {
785679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      pP2 = &P2;
795679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
805679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      // copy y2 for P2
815679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      MemoryCopy2B(&P2.y.b, &in->y2.b, sizeof(P2.y.t.buffer));
825679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      // Compute x2 HnameAlg(s2) mod p
835679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
845679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      //      do the hash operation on s2 with the size of curve 'p'
855679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      P2.x.t.size = CryptHashBlock(eccKey->publicArea.nameAlg,
865679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                   in->s2.t.size,
875679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                   in->s2.t.buffer,
885679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                   p->size,
895679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                                   P2.x.t.buffer);
905679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
915679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      // If there were error returns in the hash routine, indicate a problem
925679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      // with the hash in
935679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      if(P2.x.t.size == 0)
945679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          return TPM_RC_HASH + RC_Commit_signHandle;
955679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
965679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      // set p2.x = hash(s2) mod p
975679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      if(CryptDivide(&P2.x.b, p, NULL, &P2.x.b) != TPM_RC_SUCCESS)
985679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          return TPM_RC_NO_RESULT;
995679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
1005679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      if(!CryptEccIsPointOnCurve(parms->curveID, pP2))
1015679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          return TPM_RC_ECC_POINT + RC_Commit_s2;
1025679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
1035679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      if(eccKey->attributes.publicOnly == SET)
1045679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          return TPM_RC_KEY + RC_Commit_signHandle;
1055679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
1065679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  }
1075679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // If there is a P1, make sure that it is on the curve
1085679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // NOTE: an "empty" point has two UINT16 values which are the size values
1095679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // for each of the coordinates.
1105679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  if(in->P1.t.size > 4)
1115679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  {
1125679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      pP1 = &in->P1.t.point;
1135679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      if(!CryptEccIsPointOnCurve(parms->curveID, pP1))
1145679752bf24c21135884e987c4077e2f7184897Vadim Bendebury          return TPM_RC_ECC_POINT + RC_Commit_P1;
1155679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  }
1165679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
1175679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // Pass the parameters to CryptCommit.
1185679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // The work is not done in-line because it does several point multiplies
1195679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // with the same curve. There is significant optimization by not
1205679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  // having to reload the curve parameters multiple times.
1215679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  result = CryptCommitCompute(&out->K.t.point,
1225679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              &out->L.t.point,
1235679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              &out->E.t.point,
1245679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              parms->curveID,
1255679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              pP1,
1265679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              pP2,
1275679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              &eccKey->sensitive.sensitive.ecc,
1285679752bf24c21135884e987c4077e2f7184897Vadim Bendebury                              &r);
1295679752bf24c21135884e987c4077e2f7184897Vadim Bendebury  if(result != TPM_RC_SUCCESS)
1305679752bf24c21135884e987c4077e2f7184897Vadim Bendebury      return result;
1315679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
1325679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   out->K.t.size = TPMS_ECC_POINT_Marshal(&out->K.t.point, NULL, NULL);
1335679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   out->L.t.size = TPMS_ECC_POINT_Marshal(&out->L.t.point, NULL, NULL);
1345679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   out->E.t.size = TPMS_ECC_POINT_Marshal(&out->E.t.point, NULL, NULL);
1355679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
1365679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // The commit computation was successful so complete the commit by setting
1375679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   // the bit
1385679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   out->counter = CryptCommit();
1395679752bf24c21135884e987c4077e2f7184897Vadim Bendebury
1405679752bf24c21135884e987c4077e2f7184897Vadim Bendebury   return TPM_RC_SUCCESS;
1415679752bf24c21135884e987c4077e2f7184897Vadim Bendebury}
1425679752bf24c21135884e987c4077e2f7184897Vadim Bendebury#endif
143