decompress_privkey.c 9.7 KB

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