| // This file was extracted from the TCG Published |
| // Trusted Platform Module Library |
| // Part 3: Commands |
| // Family "2.0" |
| // Level 00 Revision 01.16 |
| // October 30, 2014 |
| |
| #include "InternalRoutines.h" |
| #include "Commit_fp.h" |
| #ifdef TPM_ALG_ECC |
| // |
| // |
| // Error Returns Meaning |
| // |
| // TPM_RC_ATTRIBUTES keyHandle references a restricted key that is not a signing key |
| // TPM_RC_ECC_POINT either P1 or the point derived from s2 is not on the curve of |
| // keyHandle |
| // TPM_RC_HASH invalid name algorithm in keyHandle |
| // TPM_RC_KEY keyHandle does not reference an ECC key |
| // TPM_RC_SCHEME the scheme of keyHandle is not an anonymous scheme |
| // TPM_RC_NO_RESULT K, L or E was a point at infinity; or failed to generate r value |
| // TPM_RC_SIZE s2 is empty but y2 is not or s2 provided but y2 is not |
| // |
| TPM_RC |
| TPM2_Commit( |
| Commit_In *in, // IN: input parameter list |
| Commit_Out *out // OUT: output parameter list |
| ) |
| { |
| OBJECT *eccKey; |
| TPMS_ECC_POINT P2; |
| TPMS_ECC_POINT *pP2 = NULL; |
| TPMS_ECC_POINT *pP1 = NULL; |
| TPM2B_ECC_PARAMETER r; |
| TPM2B *p; |
| TPM_RC result; |
| TPMS_ECC_PARMS *parms; |
| |
| // Input Validation |
| |
| eccKey = ObjectGet(in->signHandle); |
| parms = & eccKey->publicArea.parameters.eccDetail; |
| |
| // Input key must be an ECC key |
| if(eccKey->publicArea.type != TPM_ALG_ECC) |
| return TPM_RC_KEY + RC_Commit_signHandle; |
| |
| // This command may only be used with a sign-only key using an anonymous |
| // scheme. |
| // NOTE: a sign + decrypt key has no scheme so it will not be an anonymous one |
| // and an unrestricted sign key might no have a signing scheme but it can't |
| // be use in Commit() |
| if(!CryptIsSchemeAnonymous(parms->scheme.scheme)) |
| return TPM_RC_SCHEME + RC_Commit_signHandle; |
| |
| // Make sure that both parts of P2 are present if either is present |
| if((in->s2.t.size == 0) != (in->y2.t.size == 0)) |
| return TPM_RC_SIZE + RC_Commit_y2; |
| |
| // Get prime modulus for the curve. This is needed later but getting this now |
| // allows confirmation that the curve exists |
| p = (TPM2B *)CryptEccGetParameter('p', parms->curveID); |
| |
| // if no p, then the curve ID is bad |
| // |
| // NOTE: This should never occur if the input unmarshaling code is working |
| // correctly |
| pAssert(p != NULL); |
| |
| // Get the random value that will be used in the point multiplications |
| // Note: this does not commit the count. |
| if(!CryptGenerateR(&r, NULL, parms->curveID, &eccKey->name)) |
| return TPM_RC_NO_RESULT; |
| |
| // Set up P2 if s2 and Y2 are provided |
| if(in->s2.t.size != 0) |
| { |
| pP2 = &P2; |
| |
| // copy y2 for P2 |
| MemoryCopy2B(&P2.y.b, &in->y2.b, sizeof(P2.y.t.buffer)); |
| // Compute x2 HnameAlg(s2) mod p |
| |
| // do the hash operation on s2 with the size of curve 'p' |
| P2.x.t.size = CryptHashBlock(eccKey->publicArea.nameAlg, |
| in->s2.t.size, |
| in->s2.t.buffer, |
| p->size, |
| P2.x.t.buffer); |
| |
| // If there were error returns in the hash routine, indicate a problem |
| // with the hash in |
| if(P2.x.t.size == 0) |
| return TPM_RC_HASH + RC_Commit_signHandle; |
| |
| // set p2.x = hash(s2) mod p |
| if(CryptDivide(&P2.x.b, p, NULL, &P2.x.b) != TPM_RC_SUCCESS) |
| return TPM_RC_NO_RESULT; |
| |
| if(!CryptEccIsPointOnCurve(parms->curveID, pP2)) |
| return TPM_RC_ECC_POINT + RC_Commit_s2; |
| |
| if(eccKey->attributes.publicOnly == SET) |
| return TPM_RC_KEY + RC_Commit_signHandle; |
| |
| } |
| // If there is a P1, make sure that it is on the curve |
| // NOTE: an "empty" point has two UINT16 values which are the size values |
| // for each of the coordinates. |
| if(in->P1.t.size > 4) |
| { |
| pP1 = &in->P1.t.point; |
| if(!CryptEccIsPointOnCurve(parms->curveID, pP1)) |
| return TPM_RC_ECC_POINT + RC_Commit_P1; |
| } |
| |
| // Pass the parameters to CryptCommit. |
| // The work is not done in-line because it does several point multiplies |
| // with the same curve. There is significant optimization by not |
| // having to reload the curve parameters multiple times. |
| result = CryptCommitCompute(&out->K.t.point, |
| &out->L.t.point, |
| &out->E.t.point, |
| parms->curveID, |
| pP1, |
| pP2, |
| &eccKey->sensitive.sensitive.ecc, |
| &r); |
| if(result != TPM_RC_SUCCESS) |
| return result; |
| |
| out->K.t.size = TPMS_ECC_POINT_Marshal(&out->K.t.point, NULL, NULL); |
| out->L.t.size = TPMS_ECC_POINT_Marshal(&out->L.t.point, NULL, NULL); |
| out->E.t.size = TPMS_ECC_POINT_Marshal(&out->E.t.point, NULL, NULL); |
| |
| // The commit computation was successful so complete the commit by setting |
| // the bit |
| out->counter = CryptCommit(); |
| |
| return TPM_RC_SUCCESS; |
| } |
| #endif |