Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
30 | 0 | OBJECT *eccKey; |
31 | 0 | TPMS_ECC_POINT P2; |
32 | 0 | TPMS_ECC_POINT *pP2 = NULL; |
33 | 0 | TPMS_ECC_POINT *pP1 = NULL; |
34 | 0 | TPM2B_ECC_PARAMETER r; |
35 | 0 | TPM2B *p; |
36 | 0 | TPM_RC result; |
37 | 0 | TPMS_ECC_PARMS *parms; |
38 | | |
39 | | // Input Validation |
40 | |
|
41 | 0 | eccKey = ObjectGet(in->signHandle); |
42 | 0 | parms = & eccKey->publicArea.parameters.eccDetail; |
43 | | |
44 | | // Input key must be an ECC key |
45 | 0 | if(eccKey->publicArea.type != TPM_ALG_ECC) |
46 | 0 | 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 | 0 | if(!CryptIsSchemeAnonymous(parms->scheme.scheme)) |
54 | 0 | return TPM_RC_SCHEME + RC_Commit_signHandle; |
55 | | |
56 | | // Make sure that both parts of P2 are present if either is present |
57 | 0 | if((in->s2.t.size == 0) != (in->y2.t.size == 0)) |
58 | 0 | 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 | 0 | 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 | 0 | 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 | 0 | if(!CryptGenerateR(&r, NULL, parms->curveID, &eccKey->name)) |
73 | 0 | return TPM_RC_NO_RESULT; |
74 | | |
75 | | // Set up P2 if s2 and Y2 are provided |
76 | 0 | if(in->s2.t.size != 0) |
77 | 0 | { |
78 | 0 | pP2 = &P2; |
79 | | |
80 | | // copy y2 for P2 |
81 | 0 | 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 | 0 | P2.x.t.size = CryptHashBlock(eccKey->publicArea.nameAlg, |
86 | 0 | in->s2.t.size, |
87 | 0 | in->s2.t.buffer, |
88 | 0 | p->size, |
89 | 0 | P2.x.t.buffer); |
90 | | |
91 | | // If there were error returns in the hash routine, indicate a problem |
92 | | // with the hash in |
93 | 0 | if(P2.x.t.size == 0) |
94 | 0 | return TPM_RC_HASH + RC_Commit_signHandle; |
95 | | |
96 | | // set p2.x = hash(s2) mod p |
97 | 0 | if(CryptDivide(&P2.x.b, p, NULL, &P2.x.b) != TPM_RC_SUCCESS) |
98 | 0 | return TPM_RC_NO_RESULT; |
99 | | |
100 | 0 | if(!CryptEccIsPointOnCurve(parms->curveID, pP2)) |
101 | 0 | return TPM_RC_ECC_POINT + RC_Commit_s2; |
102 | | |
103 | 0 | if(eccKey->attributes.publicOnly == SET) |
104 | 0 | return TPM_RC_KEY + RC_Commit_signHandle; |
105 | |
|
106 | 0 | } |
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 | 0 | if(in->P1.t.size > 4) |
111 | 0 | { |
112 | 0 | pP1 = &in->P1.t.point; |
113 | 0 | if(!CryptEccIsPointOnCurve(parms->curveID, pP1)) |
114 | 0 | return TPM_RC_ECC_POINT + RC_Commit_P1; |
115 | 0 | } |
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 | 0 | result = CryptCommitCompute(&out->K.t.point, |
122 | 0 | &out->L.t.point, |
123 | 0 | &out->E.t.point, |
124 | 0 | parms->curveID, |
125 | 0 | pP1, |
126 | 0 | pP2, |
127 | 0 | &eccKey->sensitive.sensitive.ecc, |
128 | 0 | &r); |
129 | 0 | if(result != TPM_RC_SUCCESS) |
130 | 0 | return result; |
131 | | |
132 | 0 | out->K.t.size = TPMS_ECC_POINT_Marshal(&out->K.t.point, NULL, NULL); |
133 | 0 | out->L.t.size = TPMS_ECC_POINT_Marshal(&out->L.t.point, NULL, NULL); |
134 | 0 | 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 | 0 | out->counter = CryptCommit(); |
139 | |
|
140 | 0 | return TPM_RC_SUCCESS; |
141 | 0 | } |
142 | | #endif |