Coverage Report

Created: 2025-07-11 06:15

/src/tpm2/Commit.c
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