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