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 TPM2_Commit(Commit_In * in,Commit_Out * out)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