1 /*############################################################################
2 # Copyright 2016-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
17 /*!
18 * \file
19 * \brief EpidDecompressPrivKey implementation.
20 */
21
22 #include "epid/member/api.h"
23
24 #include "epid/common/errors.h"
25 #include "epid/common/math/ecgroup.h"
26 #include "epid/common/math/hash.h"
27 #include "epid/common/math/src/bignum-internal.h"
28 #include "epid/common/src/epid2params.h"
29 #include "epid/common/src/memory.h"
30 #include "epid/common/types.h"
31
32 /// Handle Intel(R) EPID Error with Break
33 #define BREAK_ON_EPID_ERROR(ret) \
34 if (kEpidNoErr != (ret)) { \
35 break; \
36 }
37
38 /*!
39 * \brief
40 * Internal implementation of PrivKey
41 */
42 typedef struct PrivKey_ {
43 GroupId gid; ///< group ID
44 EcPoint* A; ///< an element in G1
45 FfElement* x; ///< an integer between [0, p-1]
46 FfElement* f; ///< an integer between [0, p-1]
47 } PrivKey_;
48
49 /// Implements the derivation method used by private key decompression
50 /// Derives two integers x, f between [1, p-1] from the seed value
51 static EpidStatus DeriveXF(FpElemStr* x, FpElemStr* f, Seed const* seed,
52 FpElemStr const* p);
53
EpidDecompressPrivKey(GroupPubKey const * pub_key,CompressedPrivKey const * compressed_privkey,PrivKey * priv_key)54 EpidStatus EpidDecompressPrivKey(GroupPubKey const* pub_key,
55 CompressedPrivKey const* compressed_privkey,
56 PrivKey* priv_key) {
57 EpidStatus result = kEpidErr;
58 Epid2Params_* epid2_params = 0;
59 PrivKey_ priv_key_ = {{{0}}, 0, 0, 0};
60 FfElement* Ax = 0;
61 EcPoint* t1 = 0;
62 EcPoint* t2 = 0;
63 FfElement* t3 = 0;
64 FfElement* t4 = 0;
65 BigNum* bn_pminus1 = 0;
66 BigNum* bn_one = 0;
67 EcPoint* h1 = 0;
68 EcPoint* w = 0;
69
70 // check parameters
71 if (!pub_key || !compressed_privkey || !priv_key) {
72 return kEpidBadArgErr;
73 }
74
75 // Internal representation of Epid2Params
76 result = CreateEpid2Params(&epid2_params);
77 if (kEpidNoErr != result) {
78 return result;
79 }
80
81 do {
82 uint8_t bn_one_str = 1;
83 FpElemStr p_str = {0};
84 bool is_valid = false;
85 // shortcuts
86 EcGroup* G1 = epid2_params->G1;
87 EcGroup* G2 = epid2_params->G2;
88 FiniteField* GT = epid2_params->GT;
89 EcPoint* g1 = epid2_params->g1;
90 EcPoint* g2 = epid2_params->g2;
91 PairingState* ps_ctx = epid2_params->pairing_state;
92 FiniteField* Fp = epid2_params->Fp;
93 FiniteField* Fq = epid2_params->Fq;
94 BigNum* p = epid2_params->p;
95
96 // In the following process, temporary variables t1 (an element of
97 // G2), t2 (an element of G1), t3, t4 (elements of GT) are used.
98 // Let the compressed private key be (gid, A.x, seed). Let the
99 // Intel(R) EPID public key be (gid, h1, h2, w).
100
101 // Create a new Priv Key
102 result = NewEcPoint(G1, &priv_key_.A);
103 BREAK_ON_EPID_ERROR(result);
104 result = NewFfElement(Fp, &priv_key_.x);
105 BREAK_ON_EPID_ERROR(result);
106 result = NewFfElement(Fp, &priv_key_.f);
107 BREAK_ON_EPID_ERROR(result);
108
109 result = NewFfElement(Fq, &Ax);
110 BREAK_ON_EPID_ERROR(result);
111 result = NewEcPoint(G2, &t1);
112 BREAK_ON_EPID_ERROR(result);
113 result = NewEcPoint(G1, &t2);
114 BREAK_ON_EPID_ERROR(result);
115 result = NewFfElement(GT, &t3);
116 BREAK_ON_EPID_ERROR(result);
117 result = NewFfElement(GT, &t4);
118 BREAK_ON_EPID_ERROR(result);
119 result = NewBigNum(sizeof(BigNumStr), &bn_pminus1);
120 BREAK_ON_EPID_ERROR(result);
121 result = NewBigNum(sizeof(bn_one_str), &bn_one);
122 BREAK_ON_EPID_ERROR(result);
123
124 result = NewEcPoint(G1, &h1);
125 BREAK_ON_EPID_ERROR(result);
126 result = ReadEcPoint(G1, &(pub_key->h1), sizeof(pub_key->h1), h1);
127 BREAK_ON_EPID_ERROR(result);
128 result = NewEcPoint(G2, &w);
129 BREAK_ON_EPID_ERROR(result);
130 result = ReadEcPoint(G2, &(pub_key->w), sizeof(pub_key->w), w);
131 BREAK_ON_EPID_ERROR(result);
132
133 result = WriteBigNum(p, sizeof(p_str), &p_str);
134 BREAK_ON_EPID_ERROR(result);
135
136 result = ReadBigNum(&bn_one_str, sizeof(bn_one_str), bn_one);
137 BREAK_ON_EPID_ERROR(result);
138
139 // 1. The member derives x and f from seed. The derivation
140 // function must be the same as the one used in the key
141 // generation above. This step is out of scope of this
142 // specification.
143 result =
144 DeriveXF(&priv_key->x, &priv_key->f, &compressed_privkey->seed, &p_str);
145 BREAK_ON_EPID_ERROR(result);
146 // 2. The member computes A = G1.makePoint(A.x).
147 result = ReadFfElement(Fq, &compressed_privkey->ax,
148 sizeof(compressed_privkey->ax), Ax);
149 BREAK_ON_EPID_ERROR(result);
150 result = EcMakePoint(G1, Ax, priv_key_.A);
151 BREAK_ON_EPID_ERROR(result);
152 // 3. The member tests whether (A, x, f) is a valid Intel(R) EPID
153 // private key as follows:
154 // a. It computes t1 = G2.sscmExp(g2, x).
155 result = EcSscmExp(G2, g2, (BigNumStr const*)&priv_key->x, t1);
156 BREAK_ON_EPID_ERROR(result);
157 // b. It computes t1 = G2.mul(t1, w).
158 result = EcMul(G2, t1, w, t1);
159 BREAK_ON_EPID_ERROR(result);
160 // c. It computes t3 = pairing(A, t1).
161 result = Pairing(ps_ctx, priv_key_.A, t1, t3);
162 BREAK_ON_EPID_ERROR(result);
163 // d. It computes t2 = G1.sscmExp(h1, f).
164 result = EcSscmExp(G1, h1, (BigNumStr const*)&priv_key->f, t2);
165 BREAK_ON_EPID_ERROR(result);
166 // e. It computes t2 = G1.mul(t2, g1).
167 result = EcMul(G1, t2, g1, t2);
168 BREAK_ON_EPID_ERROR(result);
169 // f. It computes t4 = pairing(t2, g2).
170 result = Pairing(ps_ctx, t2, g2, t4);
171 BREAK_ON_EPID_ERROR(result);
172 // g. If GT.isEqual(t3, t4) = false
173 result = FfIsEqual(GT, t3, t4, &is_valid);
174 BREAK_ON_EPID_ERROR(result);
175 if (!is_valid) {
176 // i. It computes t3 = GT.exp(t3, p-1).
177 result = BigNumSub(p, bn_one, bn_pminus1);
178 BREAK_ON_EPID_ERROR(result);
179 result = FfExp(GT, t3, bn_pminus1, t3);
180 BREAK_ON_EPID_ERROR(result);
181 // ii. If GT.isEqual(t3, t4) = false again, it reports bad
182 // Intel(R) EPID private key and exits.
183 result = FfIsEqual(GT, t3, t4, &is_valid);
184 BREAK_ON_EPID_ERROR(result);
185 if (!is_valid) {
186 result = kEpidBadArgErr; // Invalid Member key
187 break;
188 }
189 // iii. It sets A = G1.inverse(A).
190 result = EcInverse(G1, priv_key_.A, priv_key_.A);
191 BREAK_ON_EPID_ERROR(result);
192 // NOTE A is modified here in this step.
193 }
194 // 4. The decompressed Intel(R) EPID private key is (gid, A, x, f).
195 // x, f already filled in.
196 priv_key->gid = pub_key->gid;
197 result = WriteEcPoint(G1, priv_key_.A, &priv_key->A, sizeof(priv_key->A));
198 BREAK_ON_EPID_ERROR(result);
199
200 result = kEpidNoErr;
201 } while (0);
202
203 DeleteEcPoint(&priv_key_.A);
204 DeleteFfElement(&priv_key_.x);
205 DeleteFfElement(&priv_key_.f);
206 DeleteFfElement(&Ax);
207 DeleteEcPoint(&t1);
208 DeleteEcPoint(&t2);
209 DeleteFfElement(&t3);
210 DeleteFfElement(&t4);
211 DeleteBigNum(&bn_pminus1);
212 DeleteBigNum(&bn_one);
213 DeleteEcPoint(&h1);
214 DeleteEcPoint(&w);
215 DeleteEpid2Params(&epid2_params);
216
217 return result;
218 }
219
220 /// Hash message buffer
221 typedef struct HashMsg {
222 /// Message to be hashed
223 char data[11];
224 } HashMsg;
225
DeriveXF(FpElemStr * x,FpElemStr * f,Seed const * seed,FpElemStr const * p)226 static EpidStatus DeriveXF(FpElemStr* x, FpElemStr* f, Seed const* seed,
227 FpElemStr const* p) {
228 EpidStatus result = kEpidErr;
229
230 BigNum* bn_x = 0;
231 BigNum* bn_f = 0;
232 BigNum* bn_p = 0;
233
234 do {
235 HashMsg msgstr = {{
236 0x00, 0x45, 0x43, 0x43, 0x2d, 0x53, 0x61, 0x66, 0x65, 0x49, 0x44,
237 }};
238 #pragma pack(1)
239 struct {
240 Seed seed;
241 HashMsg msg;
242 } hashbuf;
243 #pragma pack()
244
245 Sha256Digest digest[2];
246 Ipp8u str512[512 / 8];
247
248 result = NewBigNum(sizeof(*p), &bn_p);
249 BREAK_ON_EPID_ERROR(result);
250 result = ReadBigNum(p, sizeof(*p), bn_p);
251 BREAK_ON_EPID_ERROR(result);
252
253 result = NewBigNum(sizeof(digest), &bn_x);
254 BREAK_ON_EPID_ERROR(result);
255 result = NewBigNum(sizeof(digest), &bn_f);
256 BREAK_ON_EPID_ERROR(result);
257
258 // compute x
259 hashbuf.seed = *seed;
260 hashbuf.msg = msgstr;
261 hashbuf.msg.data[0] = 0x06;
262 result = Sha256MessageDigest(&hashbuf, sizeof(hashbuf), &digest[0]);
263 BREAK_ON_EPID_ERROR(result);
264 hashbuf.msg.data[0] = 0x07;
265 result = Sha256MessageDigest(&hashbuf, sizeof(hashbuf), &digest[1]);
266 BREAK_ON_EPID_ERROR(result);
267
268 result = ReadBigNum(&digest, sizeof(digest), bn_x);
269 BREAK_ON_EPID_ERROR(result);
270
271 result = BigNumMod(bn_x, bn_p, bn_x);
272 BREAK_ON_EPID_ERROR(result);
273
274 result = WriteBigNum(bn_x, sizeof(str512), str512);
275 BREAK_ON_EPID_ERROR(result);
276
277 *x = *(FpElemStr*)&str512[sizeof(str512) / 2];
278
279 // compute f
280 hashbuf.seed = *seed;
281 hashbuf.msg = msgstr;
282 hashbuf.msg.data[0] = 0x08;
283 result = Sha256MessageDigest(&hashbuf, sizeof(hashbuf), &digest[0]);
284 BREAK_ON_EPID_ERROR(result);
285 hashbuf.msg.data[0] = 0x09;
286 result = Sha256MessageDigest(&hashbuf, sizeof(hashbuf), &digest[1]);
287 BREAK_ON_EPID_ERROR(result);
288
289 result = ReadBigNum(&digest, sizeof(digest), bn_f);
290 BREAK_ON_EPID_ERROR(result);
291
292 result = BigNumMod(bn_f, bn_p, bn_f);
293 BREAK_ON_EPID_ERROR(result);
294
295 result = WriteBigNum(bn_f, sizeof(str512), str512);
296 BREAK_ON_EPID_ERROR(result);
297
298 *f = *(FpElemStr*)&str512[sizeof(str512) / 2];
299
300 result = kEpidNoErr;
301 } while (0);
302
303 DeleteBigNum(&bn_x);
304 DeleteBigNum(&bn_f);
305 DeleteBigNum(&bn_p);
306
307 return result;
308 }
309