| /*############################################################################ |
| # 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; |
| } |