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