• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*############################################################################
2   # Copyright 2017 Intel Corporation
3   #
4   # Licensed under the Apache License, Version 2.0 (the "License");
5   # you may not use this file except in compliance with the License.
6   # You may obtain a copy of the License at
7   #
8   #     http://www.apache.org/licenses/LICENSE-2.0
9   #
10   # Unless required by applicable law or agreed to in writing, software
11   # distributed under the License is distributed on an "AS IS" BASIS,
12   # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   # See the License for the specific language governing permissions and
14   # limitations under the License.
15   ############################################################################*/
16 /// Sensitive pre-computed signature implementation
17 /*! \file */
18 
19 #include <epid/member/api.h>
20 
21 #include <string.h>
22 
23 #include "epid/common/math/ecgroup.h"
24 #include "epid/common/math/finitefield.h"
25 #include "epid/common/src/endian_convert.h"
26 #include "epid/common/src/epid2params.h"
27 #include "epid/common/src/memory.h"
28 #include "epid/common/src/stack.h"
29 #include "epid/member/src/context.h"
30 #include "epid/member/tpm2/commit.h"
31 #include "epid/member/tpm2/context.h"
32 #include "epid/member/tpm2/getrandom.h"
33 #include "epid/member/tpm2/sign.h"
34 
35 /// Handle SDK Error with Break
36 #define BREAK_ON_EPID_ERROR(ret) \
37   if (kEpidNoErr != (ret)) {     \
38     break;                       \
39   }
40 
41 /// Count of elements in array
42 #define COUNT_OF(A) (sizeof(A) / sizeof((A)[0]))
43 
44 static EpidStatus MemberComputePreSig(MemberCtx const* ctx,
45                                       PreComputedSignature* precompsig);
46 
EpidAddPreSigs(MemberCtx * ctx,size_t number_presigs)47 EpidStatus EpidAddPreSigs(MemberCtx* ctx, size_t number_presigs) {
48   PreComputedSignature* new_presigs = NULL;
49   size_t i = 0;
50   if (!ctx || !ctx->presigs) return kEpidBadArgErr;
51 
52   if (0 == number_presigs) return kEpidNoErr;
53 
54   new_presigs =
55       (PreComputedSignature*)StackPushN(ctx->presigs, number_presigs, NULL);
56   if (!new_presigs) return kEpidMemAllocErr;
57 
58   for (i = 0; i < number_presigs; i++) {
59     EpidStatus sts = MemberComputePreSig(ctx, &new_presigs[i]);
60     if (kEpidNoErr != sts) {
61       // roll back pre-computed-signature pool
62       StackPopN(ctx->presigs, number_presigs, 0);
63       return sts;
64     }
65   }
66 
67   return kEpidNoErr;
68 }
69 
EpidGetNumPreSigs(MemberCtx const * ctx)70 size_t EpidGetNumPreSigs(MemberCtx const* ctx) {
71   return (ctx && ctx->presigs) ? StackGetSize(ctx->presigs) : (size_t)0;
72 }
73 
MemberGetPreSig(MemberCtx * ctx,PreComputedSignature * presig)74 EpidStatus MemberGetPreSig(MemberCtx* ctx, PreComputedSignature* presig) {
75   if (!ctx || !presig) {
76     return kEpidBadArgErr;
77   }
78 
79   if (StackGetSize(ctx->presigs)) {
80     // Use existing pre-computed signature
81     if (!StackPopN(ctx->presigs, 1, presig)) {
82       return kEpidErr;
83     }
84     return kEpidNoErr;
85   }
86   // generate a new pre-computed signature
87   return MemberComputePreSig(ctx, presig);
88 }
89 
90 /// Performs Pre-computation that can be used to speed up signing
MemberComputePreSig(MemberCtx const * ctx,PreComputedSignature * precompsig)91 EpidStatus MemberComputePreSig(MemberCtx const* ctx,
92                                PreComputedSignature* precompsig) {
93   EpidStatus sts = kEpidErr;
94 
95   EcPoint* B = NULL;
96   EcPoint* k = NULL;
97   EcPoint* t = NULL;  // temporary, used for K, T, R1
98   EcPoint* e = NULL;
99 
100   FfElement* R2 = NULL;
101 
102   FfElement* a = NULL;
103   FfElement* rx = NULL;  // reused for rf
104   FfElement* rb = NULL;  // reused for ra
105 
106   FfElement* t1 = NULL;
107   FfElement* t2 = NULL;
108   BigNumStr t1_str = {0};
109   BigNumStr t2_str = {0};
110   struct {
111     uint32_t i;
112     BigNumStr bsn;
113   } p2x = {0};
114   FfElement* p2y = NULL;
115 
116   if (!ctx || !precompsig || !ctx->epid2_params) {
117     return kEpidBadArgErr;
118   }
119 
120   do {
121     // handy shorthands:
122     Tpm2Ctx* tpm = ctx->tpm2_ctx;
123     EcGroup* G1 = ctx->epid2_params->G1;
124     FiniteField* GT = ctx->epid2_params->GT;
125     FiniteField* Fp = ctx->epid2_params->Fp;
126     FiniteField* Fq = ctx->epid2_params->Fq;
127     EcPoint const* h2 = ctx->h2;
128     EcPoint const* A = ctx->A;
129     FfElement const* x = ctx->x;
130     PairingState* ps_ctx = ctx->epid2_params->pairing_state;
131 
132     const BigNumStr kOne = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
134     // 1. The member expects the pre-computation is done (e12, e22, e2w,
135     //    ea2). Refer to Section 3.5 for the computation of these
136     //    values.
137 
138     sts = NewFfElement(Fq, &p2y);
139     // The following variables B, K, T, R1 (elements of G1), R2
140     // (elements of GT), a, b, rx, rf, ra, rb, t1, t2 (256-bit
141     // integers) are used.
142     BREAK_ON_EPID_ERROR(sts);
143     sts = NewEcPoint(G1, &B);
144     BREAK_ON_EPID_ERROR(sts);
145     sts = NewEcPoint(G1, &k);
146     BREAK_ON_EPID_ERROR(sts);
147     sts = NewEcPoint(G1, &t);
148     BREAK_ON_EPID_ERROR(sts);
149     sts = NewEcPoint(G1, &e);
150     BREAK_ON_EPID_ERROR(sts);
151     sts = NewFfElement(GT, &R2);
152     BREAK_ON_EPID_ERROR(sts);
153     sts = NewFfElement(Fp, &a);
154     BREAK_ON_EPID_ERROR(sts);
155     sts = NewFfElement(Fp, &rx);
156     BREAK_ON_EPID_ERROR(sts);
157     sts = NewFfElement(Fp, &rb);
158     BREAK_ON_EPID_ERROR(sts);
159     sts = NewFfElement(Fp, &t1);
160     BREAK_ON_EPID_ERROR(sts);
161     sts = NewFfElement(Fp, &t2);
162     BREAK_ON_EPID_ERROR(sts);
163 
164     // 3. The member computes B = G1.getRandom().
165     // 4.a. If bsn is not provided, the member chooses randomly an integer bsn
166     // from [1, p-1].
167     sts = Tpm2GetRandom(tpm, sizeof(p2x.bsn) * 8, &p2x.bsn);
168     BREAK_ON_EPID_ERROR(sts);
169     precompsig->rnd_bsn = p2x.bsn;
170 
171     // 4.b. The member computes (B, i2, y2) = G1.tpmHash(bsn).
172     sts = EcHash(G1, (const void*)&p2x.bsn, sizeof(p2x.bsn), ctx->hash_alg, B,
173                  &p2x.i);
174     BREAK_ON_EPID_ERROR(sts);
175     p2x.i = htonl(p2x.i);
176     sts = WriteEcPoint(G1, B, &precompsig->B, sizeof(precompsig->B));
177     BREAK_ON_EPID_ERROR(sts);
178     sts = ReadFfElement(Fq, &precompsig->B.y, sizeof(precompsig->B.y), p2y);
179     BREAK_ON_EPID_ERROR(sts);
180 
181     // 4.c. (KTPM, LTPM, ETPM, counterTPM) = TPM2_Commit(P1=h1, (s2, y2) = (i1
182     // || bsn, y2)), K = KTPM
183     sts = Tpm2Commit(tpm, ctx->h1, &p2x, sizeof(p2x), p2y, k, t, e,
184                      &precompsig->rf_ctr);
185     BREAK_ON_EPID_ERROR(sts);
186     sts = WriteEcPoint(G1, k, &precompsig->K, sizeof(precompsig->K));
187     BREAK_ON_EPID_ERROR(sts);
188     // 4.k. The member computes R1 = LTPM.
189     sts = WriteEcPoint(G1, t, &precompsig->R1, sizeof(precompsig->R1));
190     BREAK_ON_EPID_ERROR(sts);
191 
192     // 4.d. The member chooses randomly an integer a from [1, p-1].
193     sts = FfGetRandom(Fp, &kOne, ctx->rnd_func, ctx->rnd_param, a);
194     BREAK_ON_EPID_ERROR(sts);
195     sts = WriteFfElement(Fp, a, &precompsig->a, sizeof(precompsig->a));
196     BREAK_ON_EPID_ERROR(sts);
197     // 4.e. The member computes T = G1.sscmExp(h2, a).
198     sts = EcExp(G1, h2, (BigNumStr*)&precompsig->a, t);
199     BREAK_ON_EPID_ERROR(sts);
200     // 4.k. The member computes T = G1.mul(T, A).
201     sts = EcMul(G1, t, A, t);
202     BREAK_ON_EPID_ERROR(sts);
203     sts = WriteEcPoint(G1, t, &precompsig->T, sizeof(precompsig->T));
204     BREAK_ON_EPID_ERROR(sts);
205 
206     // 4.h. The member chooses rx, ra, rb randomly from [1, p-1].
207 
208     // note : rb are reused as ra
209     sts = FfGetRandom(Fp, &kOne, ctx->rnd_func, ctx->rnd_param, rx);
210     BREAK_ON_EPID_ERROR(sts);
211     sts = FfGetRandom(Fp, &kOne, ctx->rnd_func, ctx->rnd_param, rb);
212     BREAK_ON_EPID_ERROR(sts);
213 
214     sts = WriteFfElement(Fp, rx, &precompsig->rx, sizeof(precompsig->rx));
215     BREAK_ON_EPID_ERROR(sts);
216     sts = WriteFfElement(Fp, rb, &precompsig->rb, sizeof(precompsig->rb));
217     BREAK_ON_EPID_ERROR(sts);
218 
219     // 4.i. The member computes t1 = (- rx) mod p.
220     sts = FfNeg(Fp, rx, t1);
221     BREAK_ON_EPID_ERROR(sts);
222 
223     // 4.j. The member computes t2 = (rb - a * rx) mod p.
224     sts = FfMul(Fp, a, rx, t2);
225     BREAK_ON_EPID_ERROR(sts);
226     sts = FfNeg(Fp, t2, t2);
227     BREAK_ON_EPID_ERROR(sts);
228     sts = FfAdd(Fp, rb, t2, t2);
229     BREAK_ON_EPID_ERROR(sts);
230 
231     // 4.g. The member computes b = (a * x) mod p.
232     sts = FfMul(Fp, a, x, a);
233     BREAK_ON_EPID_ERROR(sts);
234     sts = WriteFfElement(Fp, a, &precompsig->b, sizeof(precompsig->b));
235     BREAK_ON_EPID_ERROR(sts);
236 
237     // reusing rb as ra
238     sts = FfGetRandom(Fp, &kOne, ctx->rnd_func, ctx->rnd_param, rb);
239     BREAK_ON_EPID_ERROR(sts);
240     sts = WriteFfElement(Fp, rb, &precompsig->ra, sizeof(precompsig->ra));
241     BREAK_ON_EPID_ERROR(sts);
242 
243     // 4.l.i e12rf = pairing(ETPM, g2)
244     sts = Pairing(ps_ctx, e, ctx->epid2_params->g2, R2);
245     BREAK_ON_EPID_ERROR(sts);
246 
247     // 4.l.ii. The member computes R2 = GT.sscmMultiExp(ea2, t1, e12rf, 1,
248     // e22, t2, e2w, ra).
249     sts = WriteFfElement(Fp, t1, &t1_str, sizeof(t1_str));
250     BREAK_ON_EPID_ERROR(sts);
251     sts = WriteFfElement(Fp, t2, &t2_str, sizeof(t2_str));
252     BREAK_ON_EPID_ERROR(sts);
253     {
254       FfElement const* points[4];
255       BigNumStr const* exponents[4];
256       points[0] = ctx->ea2;
257       points[1] = R2;
258       points[2] = ctx->e22;
259       points[3] = ctx->e2w;
260       exponents[0] = &t1_str;
261       exponents[1] = &kOne;
262       exponents[2] = &t2_str;
263       exponents[3] = (BigNumStr*)&precompsig->ra;
264       sts = FfMultiExp(GT, points, exponents, COUNT_OF(points), R2);
265       BREAK_ON_EPID_ERROR(sts);
266     }
267 
268     sts = WriteFfElement(GT, R2, &precompsig->R2, sizeof(precompsig->R2));
269     BREAK_ON_EPID_ERROR(sts);
270 
271     sts = kEpidNoErr;
272   } while (0);
273 
274   if (sts != kEpidNoErr) {
275     (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, precompsig->rf_ctr);
276   }
277 
278   EpidZeroMemory(&t1_str, sizeof(t1_str));
279   EpidZeroMemory(&t2_str, sizeof(t2_str));
280   EpidZeroMemory(&p2x, sizeof(p2x));
281 
282   DeleteFfElement(&p2y);
283   DeleteEcPoint(&B);
284   DeleteEcPoint(&k);
285   DeleteEcPoint(&t);
286   DeleteEcPoint(&e);
287   DeleteFfElement(&R2);
288   DeleteFfElement(&a);
289   DeleteFfElement(&rx);
290   DeleteFfElement(&rb);
291   DeleteFfElement(&t1);
292   DeleteFfElement(&t2);
293 
294   return sts;
295 }
296