Esempio n. 1
0
EpidStatus CreatePrivKey(PrivKey const* priv_key_str, EcGroup* G1,
                         FiniteField* Fp, PrivKey_** priv_key) {
  EpidStatus result = kEpidErr;
  PrivKey_* priv_key_ = NULL;

  // check parameters
  if (!priv_key_str || !G1 || !Fp || !priv_key) return kEpidBadArgErr;

  do {
    priv_key_ = SAFE_ALLOC(sizeof(*priv_key_));

    if (!priv_key_) {
      result = kEpidMemAllocErr;
      break;
    }

    result = NewEcPoint(G1, &priv_key_->A);
    if (kEpidNoErr != result) break;

    result = NewFfElement(Fp, &priv_key_->x);
    if (kEpidNoErr != result) break;

    result = NewFfElement(Fp, &priv_key_->f);
    if (kEpidNoErr != result) break;

    if (0 != memcpy_S(&priv_key_->gid, sizeof(priv_key_->gid),
                      &priv_key_str->gid, sizeof(priv_key_str->gid))) {
      result = kEpidBadArgErr;
      break;
    }

    result = ReadEcPoint(G1, &priv_key_str->A, sizeof(priv_key_str->A),
                         priv_key_->A);
    if (kEpidNoErr != result) break;

    result = ReadFfElement(Fp, &priv_key_str->x, sizeof(priv_key_str->x),
                           priv_key_->x);
    if (kEpidNoErr != result) break;

    result = ReadFfElement(Fp, &priv_key_str->f, sizeof(priv_key_str->f),
                           priv_key_->f);
    if (kEpidNoErr != result) break;

    *priv_key = priv_key_;
    result = kEpidNoErr;
  } while (0);

  if (kEpidNoErr != result) {
    DeletePrivKey(&priv_key_);
  }

  return (result);
}
Esempio n. 2
0
EpidStatus EpidSignBasic(MemberCtx const* ctx, void const* msg, size_t msg_len,
                         void const* basename, size_t basename_len,
                         BasicSignature* sig, BigNumStr* rnd_bsn) {
  EpidStatus sts = kEpidErr;

  EcPoint* B = NULL;
  EcPoint* t = NULL;  // temp value in G1
  EcPoint* k = NULL;
  EcPoint* e = NULL;
  FfElement* R2 = NULL;
  FfElement* p2y = NULL;
  FfElement* t1 = NULL;
  FfElement* t2 = NULL;

  FfElement* a = NULL;
  FfElement* b = NULL;
  FfElement* rx = NULL;
  FfElement* ra = NULL;
  FfElement* rb = NULL;

  struct p2x_t {
    uint32_t i;
    uint8_t bsn[1];
  }* p2x = NULL;

  FfElement* t3 = NULL;  // temporary for multiplication
  FfElement* c = NULL;
  uint8_t* digest = NULL;

  PreComputedSignature curr_presig = {0};

  if (!ctx || !sig) {
    return kEpidBadArgErr;
  }
  if (!msg && (0 != msg_len)) {
    // if message is non-empty it must have both length and content
    return kEpidBadArgErr;
  }
  if (!basename && (0 != basename_len)) {
    // if basename is non-empty it must have both length and content
    return kEpidBadArgErr;
  }
  if (!ctx->epid2_params) {
    return kEpidBadArgErr;
  }

  do {
    FiniteField* Fp = ctx->epid2_params->Fp;
    SignCommitOutput commit_out = {0};
    FpElemStr c_str = {0};
    EcGroup* G1 = ctx->epid2_params->G1;
    FiniteField* GT = ctx->epid2_params->GT;

    FiniteField* Fq = ctx->epid2_params->Fq;
    PairingState* ps_ctx = ctx->epid2_params->pairing_state;
    const BigNumStr kOne = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
    BigNumStr t1_str = {0};
    BigNumStr t2_str = {0};
    size_t digest_size = 0;
    uint16_t* rf_ctr = (uint16_t*)&ctx->rf_ctr;
    FfElement const* x = ctx->x;

    if (basename) {
      if (!IsBasenameAllowed(ctx->allowed_basenames, basename, basename_len)) {
        sts = kEpidBadArgErr;
        BREAK_ON_EPID_ERROR(sts);
      }
    }

    sts = NewEcPoint(G1, &B);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewEcPoint(G1, &k);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewEcPoint(G1, &t);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewEcPoint(G1, &e);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(GT, &R2);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fq, &p2y);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &t1);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &t2);
    BREAK_ON_EPID_ERROR(sts);
    p2x = (struct p2x_t*)SAFE_ALLOC(sizeof(struct p2x_t) + basename_len - 1);
    if (!p2x) {
      sts = kEpidMemAllocErr;
      break;
    }

    sts = NewFfElement(Fp, &a);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &b);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &rx);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &ra);
    BREAK_ON_EPID_ERROR(sts);
    sts = NewFfElement(Fp, &rb);
    BREAK_ON_EPID_ERROR(sts);

    sts = MemberGetPreSig((MemberCtx*)ctx, &curr_presig);
    BREAK_ON_EPID_ERROR(sts);

    // 3.  If the pre-computed signature pre-sigma exists, the member
    //     loads (B, K, T, a, b, rx, rf, ra, rb, R1, R2) from
    //     pre-sigma. Refer to Section 4.4 for the computation of
    //     these values.
    sts = ReadFfElement(Fp, &curr_presig.a, sizeof(curr_presig.a), a);
    BREAK_ON_EPID_ERROR(sts);
    sts = ReadFfElement(Fp, &curr_presig.b, sizeof(curr_presig.b), b);
    BREAK_ON_EPID_ERROR(sts);
    sts = ReadFfElement(Fp, &curr_presig.rx, sizeof(curr_presig.rx), rx);
    BREAK_ON_EPID_ERROR(sts);
    sts = ReadFfElement(Fp, &curr_presig.ra, sizeof(curr_presig.ra), ra);
    BREAK_ON_EPID_ERROR(sts);
    sts = ReadFfElement(Fp, &curr_presig.rb, sizeof(curr_presig.rb), rb);
    BREAK_ON_EPID_ERROR(sts);

    // If the basename is provided, use it, otherwise use presig B
    if (basename) {
      // 3.a. The member computes (B, i2, y2) = G1.tpmHash(bsn).
      sts = EcHash(G1, basename, basename_len, ctx->hash_alg, B, &p2x->i);
      BREAK_ON_EPID_ERROR(sts);
      p2x->i = htonl(p2x->i);
      sts = WriteEcPoint(G1, B, &commit_out.B, sizeof(commit_out.B));
      BREAK_ON_EPID_ERROR(sts);
      sts = ReadFfElement(Fq, &commit_out.B.y, sizeof(commit_out.B.y), p2y);
      BREAK_ON_EPID_ERROR(sts);

      // b.i. (KTPM, LTPM, ETPM, counterTPM) = TPM2_Commit(P1=h1,(s2, y2) = (i2
      // || bsn, y2)).
      // b.ii.K = KTPM.
      if (0 !=
          memcpy_S((void*)p2x->bsn, basename_len, basename, basename_len)) {
        sts = kEpidBadArgErr;
        break;
      }
      sts =
          Tpm2Commit(ctx->tpm2_ctx, ctx->h1, p2x, sizeof(p2x->i) + basename_len,
                     p2y, k, t, e, (uint16_t*)&ctx->rf_ctr);
      BREAK_ON_EPID_ERROR(sts);
      sts = WriteEcPoint(G1, k, &commit_out.K, sizeof(commit_out.K));
      BREAK_ON_EPID_ERROR(sts);
      // c.i. The member computes R1 = LTPM.
      sts = WriteEcPoint(G1, t, &commit_out.R1, sizeof(commit_out.R1));
      BREAK_ON_EPID_ERROR(sts);
      // c.ii. e12rf = pairing(ETPM, g2)
      sts = Pairing(ps_ctx, e, ctx->epid2_params->g2, R2);
      BREAK_ON_EPID_ERROR(sts);
      // c.iii. R2 = GT.sscmMultiExp(ea2, t1, e12rf, 1, e22, t2, e2w,ra).
      // 4.i. The member computes t1 = (- rx) mod p.
      sts = FfNeg(Fp, rx, t1);
      BREAK_ON_EPID_ERROR(sts);
      // 4.j. The member computes t2 = (rb - a * rx) mod p.
      sts = FfMul(Fp, a, rx, t2);
      BREAK_ON_EPID_ERROR(sts);
      sts = FfNeg(Fp, t2, t2);
      BREAK_ON_EPID_ERROR(sts);
      sts = FfAdd(Fp, rb, t2, t2);
      BREAK_ON_EPID_ERROR(sts);

      sts = WriteFfElement(Fp, t1, &t1_str, sizeof(t1_str));
      BREAK_ON_EPID_ERROR(sts);
      sts = WriteFfElement(Fp, t2, &t2_str, sizeof(t2_str));
      BREAK_ON_EPID_ERROR(sts);
      {
        FfElement const* points[4];
        BigNumStr const* exponents[4];
        points[0] = ctx->ea2;
        points[1] = R2;
        points[2] = ctx->e22;
        points[3] = ctx->e2w;
        exponents[0] = &t1_str;
        exponents[1] = &kOne;
        exponents[2] = &t2_str;
        exponents[3] = (BigNumStr*)&curr_presig.ra;
        sts = FfMultiExp(GT, points, exponents, COUNT_OF(points), R2);
        BREAK_ON_EPID_ERROR(sts);
      }

      sts = WriteFfElement(GT, R2, &commit_out.R2, sizeof(commit_out.R2));
      BREAK_ON_EPID_ERROR(sts);
      // d. The member over-writes the counterTPM, B, K, R1 and R2 values.
    } else {
      if (!rnd_bsn) {
        sts = kEpidBadArgErr;
        break;
      }
      sts = ReadEcPoint(G1, &curr_presig.B, sizeof(curr_presig.B), B);
      BREAK_ON_EPID_ERROR(sts);
      commit_out.B = curr_presig.B;
      commit_out.K = curr_presig.K;
      commit_out.R1 = curr_presig.R1;
      ((MemberCtx*)ctx)->rf_ctr = curr_presig.rf_ctr;
      commit_out.R2 = curr_presig.R2;
      *rnd_bsn = curr_presig.rnd_bsn;
    }

    commit_out.T = curr_presig.T;

    sts = HashSignCommitment(Fp, ctx->hash_alg, &ctx->pub_key, &commit_out, msg,
                             msg_len, &c_str);
    BREAK_ON_EPID_ERROR(sts);

    digest_size = EpidGetHashSize(ctx->hash_alg);
    digest = (uint8_t*)SAFE_ALLOC(digest_size);
    if (!digest) {
      sts = kEpidNoMemErr;
      break;
    }
    memcpy_S(digest + digest_size - sizeof(c_str), sizeof(c_str), &c_str,
             sizeof(c_str));

    sts = NewFfElement(Fp, &t3);
    BREAK_ON_EPID_ERROR(sts);

    sts = NewFfElement(Fp, &c);
    BREAK_ON_EPID_ERROR(sts);

    sts = ReadFfElement(Fp, &c_str, sizeof(c_str), c);
    BREAK_ON_EPID_ERROR(sts);

    // 7.  The member computes sx = (rx + c * x) mod p.
    sts = FfMul(Fp, c, x, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = FfAdd(Fp, rx, t3, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, t3, &sig->sx, sizeof(sig->sx));
    BREAK_ON_EPID_ERROR(sts);

    // 8.  The member computes sf = (rf + c * f) mod p.
    sts = Tpm2Sign(ctx->tpm2_ctx, digest, digest_size, *rf_ctr, NULL, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, t3, &sig->sf, sizeof(sig->sf));
    BREAK_ON_EPID_ERROR(sts);

    // 9.  The member computes sa = (ra + c * a) mod p.
    sts = FfMul(Fp, c, a, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = FfAdd(Fp, ra, t3, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, t3, &sig->sa, sizeof(sig->sa));
    BREAK_ON_EPID_ERROR(sts);

    // 10. The member computes sb = (rb + c * b) mod p.
    sts = FfMul(Fp, c, b, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = FfAdd(Fp, rb, t3, t3);
    BREAK_ON_EPID_ERROR(sts);
    sts = WriteFfElement(Fp, t3, &sig->sb, sizeof(sig->sb));
    BREAK_ON_EPID_ERROR(sts);

    sig->B = commit_out.B;
    sig->K = commit_out.K;
    sig->T = commit_out.T;
    sig->c = c_str;

    sts = kEpidNoErr;
  } while (0);

  if (sts != kEpidNoErr) {
    (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, (uint16_t)ctx->rf_ctr);
    (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, curr_presig.rf_ctr);
  } else if (basename) {
    (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, curr_presig.rf_ctr);
  }

  EpidZeroMemory(&curr_presig, sizeof(curr_presig));

  DeleteEcPoint(&B);
  DeleteEcPoint(&k);
  DeleteEcPoint(&t);
  DeleteEcPoint(&e);
  DeleteFfElement(&R2);
  DeleteFfElement(&p2y);
  DeleteFfElement(&t1);
  DeleteFfElement(&t2);

  DeleteFfElement(&a);
  DeleteFfElement(&b);
  DeleteFfElement(&rx);
  DeleteFfElement(&ra);
  DeleteFfElement(&rb);

  SAFE_FREE(p2x);

  DeleteFfElement(&t3);
  DeleteFfElement(&c);
  SAFE_FREE(digest);

  return sts;
}
Esempio n. 3
0
/// Parse a file with a revocation list of any type
static EpidStatus EpidParseRlFile(void const* buf, size_t len,
                                  EpidCaCertificate const* cert, void* rl,
                                  size_t* rl_len, EpidFileType file_type) {
  size_t min_rl_file_size = 0;
  size_t empty_rl_size = 0;
  size_t rl_entry_size = 0;
  EpidStatus result = kEpidErr;
  EpidFileHeader const* file_header = (EpidFileHeader*)buf;
  void const* buf_rl =
      (void const*)((unsigned char*)buf + sizeof(EpidFileHeader));
  size_t buf_rl_len = 0;
  EcdsaSignature const* signature = NULL;

  if (!buf || !cert || !rl_len) return kEpidBadArgErr;

  switch (file_type) {
    case kPrivRlFile:
      empty_rl_size = sizeof(PrivRl) - sizeof(((PrivRl*)0)->f[0]);
      rl_entry_size = sizeof(((PrivRl*)0)->f[0]);
      min_rl_file_size = sizeof(EpidFileHeader) + sizeof(PrivRl) -
                         sizeof(((PrivRl*)0)->f[0]) + sizeof(EcdsaSignature);
      break;
    case kSigRlFile:
      empty_rl_size = sizeof(SigRl) - sizeof(((SigRl*)0)->bk[0]);
      rl_entry_size = sizeof(((SigRl*)0)->bk[0]);
      min_rl_file_size = sizeof(EpidFileHeader) + sizeof(SigRl) -
                         sizeof(((SigRl*)0)->bk[0]) + sizeof(EcdsaSignature);
      break;
    case kGroupRlFile:
      empty_rl_size = sizeof(GroupRl) - sizeof(((GroupRl*)0)->gid[0]);
      rl_entry_size = sizeof(((GroupRl*)0)->gid[0]);
      min_rl_file_size = sizeof(EpidFileHeader) + sizeof(GroupRl) -
                         sizeof(((GroupRl*)0)->gid[0]) + sizeof(EcdsaSignature);
      break;
    default:
      return kEpidErr;
  }

  if (min_rl_file_size > len) return kEpidBadArgErr;

  // Verify that Intel(R) EPID file header in the buffer is correct
  if (0 !=
      memcmp(&file_header->epid_version, &kEpidVersion, sizeof(kEpidVersion))) {
    return kEpidBadArgErr;
  }
  if (0 != memcmp(&file_header->file_type, &kEpidFileTypeCode[file_type],
                  sizeof(file_header->file_type))) {
    return kEpidBadArgErr;
  }

  // Verify that CA certificate is correct
  result = EpidVerifyCaCertificate(cert);
  if (kEpidNoErr != result) return result;

  // Verify that RL in file buffer contains of integer number of entries
  buf_rl_len = len - sizeof(EpidFileHeader) - sizeof(EcdsaSignature);
  if (0 != ((buf_rl_len - empty_rl_size) % rl_entry_size)) {
    return kEpidBadArgErr;
  }

  signature =
      (EcdsaSignature*)((unsigned char*)buf + len - sizeof(EcdsaSignature));
  // Authenticate signature for buffer
  result = EcdsaVerifyBuffer(buf, len - sizeof(EcdsaSignature),
                             (EcdsaPublicKey*)&cert->pubkey, signature);
  if (kEpidSigValid != result) return result;

  buf_rl_len = len - sizeof(EpidFileHeader) - sizeof(EcdsaSignature);

  // If pointer to output buffer is NULL it should return required size of RL
  if (!rl) {
    *rl_len = buf_rl_len;
    return kEpidNoErr;
  }

  if (*rl_len < buf_rl_len) return kEpidBadArgErr;
  *rl_len = buf_rl_len;

  // Copy revocation list from file buffer to output
  // Memory copy is used to copy a revocation list of variable length
  if (0 != memcpy_S(rl, *rl_len, buf_rl, buf_rl_len)) return kEpidBadArgErr;

  return kEpidNoErr;
}
Esempio n. 4
0
EpidStatus EpidSign(MemberCtx const* ctx, void const* msg, size_t msg_len,
                    void const* basename, size_t basename_len,
                    SigRl const* sig_rl, size_t sig_rl_size, EpidSignature* sig,
                    size_t sig_len) {
  EpidStatus result = kEpidErr;
  uint32_t num_sig_rl = 0;
  OctStr32 octstr32_0 = {{0x00, 0x00, 0x00, 0x00}};
  if (!ctx || !sig) {
    return kEpidBadArgErr;
  }
  if (!ctx->pub_key) {
    return kEpidBadArgErr;
  }
  if (!msg && (0 != msg_len)) {
    // if message is non-empty it must have both length and content
    return kEpidBadArgErr;
  }
  if (!basename && (0 != basename_len)) {
    // if basename is non-empty it must have both length and content
    return kEpidBadArgErr;
  }
  if (sig_rl && (sig_rl_size < sizeof(SigRl) - sizeof(SigRlEntry))) {
    return kEpidBadArgErr;
  }
  if (sig_rl && EpidGetSigSize(sig_rl) > sig_len) {
    return kEpidBadArgErr;
  }

  // 11. The member sets sigma0 = (B, K, T, c, sx, sf, sa, sb).
  result =
      EpidSignBasic(ctx, msg, msg_len, basename, basename_len, &sig->sigma0);
  if (kEpidNoErr != result) {
    return result;
  }

  if (!sig_rl) {
    // 12. If SigRL is not provided as input,
    //   a. The member sets RLver = 0 and n2 = 0.
    //   b. The member outputs (sigma0, RLver, n2) and returns "succeeded".
    sig->rl_ver = octstr32_0;
    sig->n2 = octstr32_0;
    return kEpidNoErr;
  } else {
    uint32_t i = 0;
    EpidStatus nr_prove_status = kEpidNoErr;
    // 13. If SigRL is provided as input, the member proceeds with
    //     the following steps:
    //   a. The member verifies that gid in public key and in SigRL
    //      match.
    if (!IsSigRlValid(&ctx->pub_key->gid, sig_rl, sig_rl_size)) {
      return kEpidBadArgErr;
    }
    //   b. The member copies RLver and n2 values in SigRL to the
    //      signature.
    if (0 != memcpy_S(&sig->rl_ver, sizeof(sig->rl_ver), &sig_rl->version,
                      sizeof(sig_rl->version)))
      return kEpidBadArgErr;
    if (0 !=
        memcpy_S(&sig->n2, sizeof(sig->n2), &sig_rl->n2, sizeof(sig_rl->n2)))
      return kEpidBadArgErr;
    //   c. For i = 0, ..., n2-1, the member computes sigma[i] =
    //      nrProve(f, B, K, B[i], K[i]). The details of nrProve()
    //      will be given in the next subsection.
    num_sig_rl = ntohl(sig_rl->n2);
    for (i = 0; i < num_sig_rl; i++) {
      result = EpidNrProve(ctx, msg, msg_len, &sig->sigma0, &sig_rl->bk[i],
                           &sig->sigma[i]);
      if (kEpidNoErr != result) {
        nr_prove_status = result;
      }
    }
    if (kEpidNoErr != nr_prove_status) {
      memset(&sig->sigma[0], 0, num_sig_rl * sizeof(sig->sigma[0]));
      return nr_prove_status;
    }
  }
  //   d. The member outputs (sigma0, RLver, n2, sigma[0], ...,
  //      sigma[n2-1]).
  //   e. If any of the nrProve() functions outputs "failed", the
  //      member returns "revoked", otherwise returns "succeeded".
  return kEpidNoErr;
}