/*############################################################################
# Copyright 2017 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
############################################################################*/
/// Member private exponentiation implementation
/*! \file */
#include "epid/member/src/privateexp.h"
#include "epid/common/math/ecgroup.h"
#include "epid/common/src/epid2params.h"
#include "epid/common/src/hashsize.h"
#include "epid/common/src/memory.h"
#include "epid/common/types.h"
#include "epid/member/src/context.h"
#include "epid/member/tpm2/commit.h"
#include "epid/member/tpm2/sign.h"
/// Handle Intel(R) EPID Error with Break
#define BREAK_ON_EPID_ERROR(ret) \
if (kEpidNoErr != (ret)) { \
break; \
}
EpidStatus EpidPrivateExp(MemberCtx* ctx, EcPoint const* a, EcPoint* r) {
EpidStatus sts = kEpidErr;
BigNumStr tmp_ff_str = {0};
uint16_t counter = 0;
EcPoint* k_pt = NULL;
EcPoint* l_pt = NULL;
EcPoint* e_pt = NULL;
EcPoint* t1 = NULL;
EcPoint* h = NULL;
FfElement* k = NULL;
FfElement* s = NULL;
size_t digest_len = 0;
uint8_t* digest = NULL;
if (!ctx || !ctx->epid2_params || !a || !r) {
return kEpidBadArgErr;
}
digest_len = EpidGetHashSize(ctx->hash_alg);
digest = SAFE_ALLOC(digest_len);
if (!digest) {
return kEpidMemAllocErr;
}
memset(digest, 0, digest_len);
digest[digest_len - 1] = 1;
do {
FiniteField* Fp = ctx->epid2_params->Fp;
EcGroup* G1 = ctx->epid2_params->G1;
if (!ctx->is_provisioned && !ctx->is_initially_provisioned) {
sts = EpidMemberInitialProvision(ctx);
BREAK_ON_EPID_ERROR(sts);
}
// (K_PT, L_PT, E_PT, counter) = TPM2_Commit(P1=B')
sts = NewEcPoint(G1, &k_pt);
BREAK_ON_EPID_ERROR(sts);
sts = NewEcPoint(G1, &l_pt);
BREAK_ON_EPID_ERROR(sts);
sts = NewEcPoint(G1, &e_pt);
BREAK_ON_EPID_ERROR(sts);
sts = NewEcPoint(G1, &t1);
BREAK_ON_EPID_ERROR(sts);
sts = NewEcPoint(G1, &h);
BREAK_ON_EPID_ERROR(sts);
sts =
Tpm2Commit(ctx->tpm2_ctx, a, NULL, 0, NULL, k_pt, l_pt, e_pt, &counter);
BREAK_ON_EPID_ERROR(sts);
// (k, s) = TPM2_Sign(c=1, counter)
sts = NewFfElement(Fp, &k);
BREAK_ON_EPID_ERROR(sts);
sts = NewFfElement(Fp, &s);
BREAK_ON_EPID_ERROR(sts);
sts = Tpm2Sign(ctx->tpm2_ctx, digest, digest_len, counter, k, s);
BREAK_ON_EPID_ERROR(sts);
// k = Fq.inv(k)
sts = FfInv(Fp, k, k);
BREAK_ON_EPID_ERROR(sts);
// t1 = G1.sscmExp(B', s)
sts = WriteFfElement(Fp, s, &tmp_ff_str, sizeof(tmp_ff_str));
BREAK_ON_EPID_ERROR(sts);
sts = EcSscmExp(G1, a, &tmp_ff_str, t1);
BREAK_ON_EPID_ERROR(sts);
// E_PT = G1.inv(E_PT)
sts = EcInverse(G1, e_pt, e_pt);
BREAK_ON_EPID_ERROR(sts);
// h = G1.mul(t1, E_PT)
sts = EcMul(G1, t1, e_pt, h);
BREAK_ON_EPID_ERROR(sts);
// h = G1.sscmExp(h, k)
sts = WriteFfElement(Fp, k, &tmp_ff_str, sizeof(tmp_ff_str));
BREAK_ON_EPID_ERROR(sts);
sts = EcSscmExp(G1, h, &tmp_ff_str, r);
BREAK_ON_EPID_ERROR(sts);
} while (0);
if (sts != kEpidNoErr) {
(void)Tpm2ReleaseCounter(ctx->tpm2_ctx, counter);
}
DeleteFfElement(&s);
DeleteFfElement(&k);
DeleteEcPoint(&e_pt);
DeleteEcPoint(&l_pt);
DeleteEcPoint(&k_pt);
DeleteEcPoint(&t1);
DeleteEcPoint(&h);
EpidZeroMemory(&tmp_ff_str, sizeof(tmp_ff_str));
SAFE_FREE(digest);
return sts;
}