aboutsummaryrefslogtreecommitdiff
path: root/epid/member/tpm2/src/commit.c
blob: 571508251204c54d5397da33f917452aeaffb6fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*############################################################################
# Copyright 2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
############################################################################*/
/// Tpm2Commit implementation.
/*! \file */

#include "epid/member/tpm2/commit.h"
#include "epid/common/math/ecgroup.h"
#include "epid/common/math/finitefield.h"
#include "epid/common/src/epid2params.h"
#include "epid/common/src/memory.h"
#include "epid/member/tpm2/src/state.h"

/// Handle Intel(R) EPID Error with Break
#define BREAK_ON_EPID_ERROR(ret) \
  if (kEpidNoErr != (ret)) {     \
    break;                       \
  }

static EpidStatus InsertR(Tpm2Ctx* ctx, FfElement* r, uint16_t* counter) {
  uint16_t index = 0;
  if (!ctx || !r || !counter) {
    return kEpidBadArgErr;
  }
  for (index = 0; index < MAX_COMMIT_COUNT; ++index) {
    if (!ctx->commit_data[index]) {
      ctx->commit_data[index] = r;
      break;
    }
  }
  if (index == MAX_COMMIT_COUNT) {
    return kEpidMemAllocErr;
  }
  *counter = index + 1;  // counter == 0 should be invalid
  return kEpidNoErr;
}

static void DeleteR(Tpm2Ctx* ctx, uint16_t* counter) {
  if (counter && *counter != 0 && *counter <= MAX_COMMIT_COUNT) {
    DeleteFfElement(&ctx->commit_data[*counter - 1]);
    *counter = 0;
  }
}

EpidStatus Tpm2Commit(Tpm2Ctx* ctx, EcPoint const* p1, void const* s2,
                      size_t s2_len, FfElement const* y2, EcPoint* k,
                      EcPoint* l, EcPoint* e, uint16_t* counter) {
  EpidStatus sts = kEpidErr;
  FiniteField* Fp = NULL;
  FiniteField* Fq = NULL;
  EcGroup* G1 = NULL;
  FfElement* x2 = NULL;
  FfElement* r = NULL;
  EcPoint* point = NULL;
  EcPoint* infinity = NULL;
  uint16_t ctr = 0;

  if (!ctx || !ctx->epid2_params || !ctx->f) {
    return kEpidBadArgErr;
  }

  if (s2 && s2_len <= 0) {
    return kEpidBadArgErr;
  }

  if ((!s2 && y2) || (s2 && !y2)) {
    return kEpidBadArgErr;
  }

  if (s2 && (!k || !l)) {
    return kEpidBadArgErr;
  }

  if (!e || !counter) {
    return kEpidBadArgErr;
  }

  do {
    G1ElemStr point_str = {0};
    BigNumStr r_str = {0};
    const BigNumStr kOne = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
    bool is_equal = false;
    Fp = ctx->epid2_params->Fp;
    Fq = ctx->epid2_params->Fq;
    G1 = ctx->epid2_params->G1;

    sts = NewEcPoint(G1, &infinity);
    BREAK_ON_EPID_ERROR(sts);
    // step b
    if (s2) {
      // step c: compute x2 := HnameAlg(s2) mod p
      sts = NewFfElement(Fq, &x2);
      BREAK_ON_EPID_ERROR(sts);
      sts = FfHash(Fq, s2, s2_len, ctx->hash_alg, x2);
      BREAK_ON_EPID_ERROR(sts);

      // step d: if (x2, y2) is not a point on the curve of signHandle, return
      // TPM_RC_ECC_POINT
      sts = NewEcPoint(G1, &point);
      BREAK_ON_EPID_ERROR(sts);
      sts = WriteFfElement(Fq, x2, &point_str.x, sizeof(point_str.x));
      BREAK_ON_EPID_ERROR(sts);
      sts = WriteFfElement(Fq, y2, &point_str.y, sizeof(point_str.y));
      BREAK_ON_EPID_ERROR(sts);
      sts = ReadEcPoint(G1, &point_str, sizeof(point_str), point);
      BREAK_ON_EPID_ERROR(sts);
    }

    // step e: if p1 is not an Empty Point and p1 is not a point on the curve of
    // signHandle, return TPM_RC_ECC_POINT
    // This step is guranteed by ReadEcPoint SDK function

    // step g: generate or derive r (see C.2.2)
    // step h: set r = r mod n
    sts = NewFfElement(Fp, &r);
    BREAK_ON_EPID_ERROR(sts);
    sts = FfGetRandom(Fp, &kOne, ctx->rnd_func, ctx->rnd_param, r);
    BREAK_ON_EPID_ERROR(sts);
    sts = InsertR(ctx, r, &ctr);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, r, &r_str, sizeof(r_str));
    BREAK_ON_EPID_ERROR(sts);
    // step i: if s2 is not an Empty Buffer, set K = [ds](x2, y2) and L =
    // [r](x2, y2)
    if (s2) {
      BigNumStr f_str = {0};
      do {
        sts = WriteFfElement(Fp, ctx->f, &f_str, sizeof(f_str));
        BREAK_ON_EPID_ERROR(sts);
        sts = EcExp(G1, point, &f_str, k);
        BREAK_ON_EPID_ERROR(sts);
      } while (0);
      EpidZeroMemory(&f_str, sizeof(f_str));
      BREAK_ON_EPID_ERROR(sts);
      sts = EcExp(G1, point, &r_str, l);
      BREAK_ON_EPID_ERROR(sts);
      sts = EcIsEqual(G1, k, infinity, &is_equal);
      BREAK_ON_EPID_ERROR(sts);
      if (is_equal) {
        sts = kEpidBadArgErr;
        break;
      }
      sts = EcIsEqual(G1, l, infinity, &is_equal);
      BREAK_ON_EPID_ERROR(sts);
      if (is_equal) {
        sts = kEpidBadArgErr;
        break;
      }
    }
    // step j: if p1 is not an Empty Point, set E = [r](p1 )
    if (p1) {
      sts = EcExp(G1, p1, &r_str, e);
      BREAK_ON_EPID_ERROR(sts);
    } else {
      // step k: if p1 is an Empty Point and s2 is an Empty Buffer, set E = [r]G
      sts = EcExp(G1, ctx->epid2_params->g1, &r_str, e);
      BREAK_ON_EPID_ERROR(sts);
    }
    sts = EcIsEqual(G1, e, infinity, &is_equal);
    BREAK_ON_EPID_ERROR(sts);
    if (is_equal) {
      sts = kEpidBadArgErr;
      break;
    }
    *counter = ctr;
  } while (0);

  if (sts != kEpidNoErr) {
    DeleteR(ctx, &ctr);
  }
  DeleteEcPoint(&infinity);
  DeleteEcPoint(&point);
  DeleteFfElement(&x2);
  return sts;
}