Vadim Bendebury | 5679752 | 2015-05-20 10:32:25 -0700 | [diff] [blame] | 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 |