Home | History | Annotate | Download | only in src
      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 
     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 
    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