| /*############################################################################ |
| # Copyright 2016-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. |
| ############################################################################*/ |
| |
| /*! |
| * \file |
| * \brief Member context implementation. |
| */ |
| |
| #include <epid/member/api.h> |
| |
| #include <string.h> |
| #include "epid/common/src/endian_convert.h" |
| #include "epid/common/src/epid2params.h" |
| #include "epid/common/src/memory.h" |
| #include "epid/common/src/sigrlvalid.h" |
| #include "epid/common/src/stack.h" |
| #include "epid/common/types.h" |
| #include "epid/member/software_member.h" |
| #include "epid/member/src/allowed_basenames.h" |
| #include "epid/member/src/context.h" |
| #include "epid/member/src/precomp.h" |
| #include "epid/member/tpm2/context.h" |
| #include "epid/member/tpm2/createprimary.h" |
| #include "epid/member/tpm2/load_external.h" |
| #include "epid/member/tpm2/sign.h" |
| |
| /// Handle SDK Error with Break |
| #define BREAK_ON_EPID_ERROR(ret) \ |
| if (kEpidNoErr != (ret)) { \ |
| break; \ |
| } |
| |
| EpidStatus EpidMemberGetSize(MemberParams const* params, size_t* context_size) { |
| if (!params || !context_size) { |
| return kEpidBadArgErr; |
| } |
| *context_size = sizeof(MemberCtx); |
| return kEpidNoErr; |
| } |
| |
| EpidStatus EpidMemberInit(MemberParams const* params, MemberCtx* ctx) { |
| EpidStatus sts = kEpidErr; |
| |
| if (!params || !ctx) { |
| return kEpidBadArgErr; |
| } |
| memset(ctx, 0, sizeof(*ctx)); |
| do { |
| const FpElemStr* f = NULL; |
| |
| // set the default hash algorithm to sha512 |
| ctx->hash_alg = kSha512; |
| #ifdef TPM_TSS // if build for TSS, make Sha256 default |
| ctx->hash_alg = kSha256; |
| #endif |
| ctx->sig_rl = NULL; |
| ctx->precomp_ready = false; |
| ctx->is_initially_provisioned = false; |
| ctx->is_provisioned = false; |
| ctx->primary_key_set = false; |
| |
| sts = CreateBasenames(&ctx->allowed_basenames); |
| BREAK_ON_EPID_ERROR(sts); |
| // Internal representation of Epid2Params |
| sts = CreateEpid2Params(&ctx->epid2_params); |
| BREAK_ON_EPID_ERROR(sts); |
| |
| // create TPM2 context |
| sts = Tpm2CreateContext(params, ctx->epid2_params, &ctx->rnd_func, |
| &ctx->rnd_param, &f, &ctx->tpm2_ctx); |
| BREAK_ON_EPID_ERROR(sts); |
| |
| if (!CreateStack(sizeof(PreComputedSignature), &ctx->presigs)) { |
| sts = kEpidMemAllocErr; |
| BREAK_ON_EPID_ERROR(sts); |
| } |
| |
| ctx->f = f; |
| ctx->join_ctr = 0; |
| ctx->rf_ctr = 0; |
| ctx->rnu_ctr = 0; |
| |
| sts = NewEcPoint(ctx->epid2_params->G1, (EcPoint**)&ctx->A); |
| BREAK_ON_EPID_ERROR(sts); |
| sts = NewFfElement(ctx->epid2_params->Fp, (FfElement**)&ctx->x); |
| BREAK_ON_EPID_ERROR(sts); |
| |
| sts = NewEcPoint(ctx->epid2_params->G1, (EcPoint**)&ctx->h1); |
| BREAK_ON_EPID_ERROR(sts); |
| sts = NewEcPoint(ctx->epid2_params->G1, (EcPoint**)&ctx->h2); |
| BREAK_ON_EPID_ERROR(sts); |
| sts = NewEcPoint(ctx->epid2_params->G2, (EcPoint**)&ctx->w); |
| BREAK_ON_EPID_ERROR(sts); |
| |
| sts = NewFfElement(ctx->epid2_params->GT, (FfElement**)&ctx->e12); |
| BREAK_ON_EPID_ERROR(sts); |
| sts = NewFfElement(ctx->epid2_params->GT, (FfElement**)&ctx->e22); |
| BREAK_ON_EPID_ERROR(sts); |
| sts = NewFfElement(ctx->epid2_params->GT, (FfElement**)&ctx->e2w); |
| BREAK_ON_EPID_ERROR(sts); |
| sts = NewFfElement(ctx->epid2_params->GT, (FfElement**)&ctx->ea2); |
| BREAK_ON_EPID_ERROR(sts); |
| |
| sts = Tpm2SetHashAlg(ctx->tpm2_ctx, ctx->hash_alg); |
| BREAK_ON_EPID_ERROR(sts); |
| ctx->primary_key_set = true; |
| sts = kEpidNoErr; |
| } while (0); |
| if (kEpidNoErr != sts) { |
| EpidMemberDeinit(ctx); |
| } |
| |
| return (sts); |
| } |
| |
| void EpidMemberDeinit(MemberCtx* ctx) { |
| size_t i = 0; |
| size_t presig_size = 0; |
| PreComputedSignature* buf = NULL; |
| if (!ctx) { |
| return; |
| } |
| presig_size = StackGetSize(ctx->presigs); |
| buf = StackGetBuf(ctx->presigs); |
| for (i = 0; i < presig_size; ++i) { |
| (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, (buf++)->rf_ctr); |
| } |
| (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, ctx->join_ctr); |
| (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, ctx->rf_ctr); |
| (void)Tpm2ReleaseCounter(ctx->tpm2_ctx, ctx->rnu_ctr); |
| DeleteStack(&ctx->presigs); |
| ctx->rnd_param = NULL; |
| DeleteEcPoint((EcPoint**)&(ctx->h1)); |
| DeleteEcPoint((EcPoint**)&(ctx->h2)); |
| DeleteEcPoint((EcPoint**)&(ctx->A)); |
| DeleteFfElement((FfElement**)&ctx->x); |
| DeleteEcPoint((EcPoint**)&(ctx->w)); |
| DeleteFfElement((FfElement**)&ctx->e12); |
| DeleteFfElement((FfElement**)&ctx->e22); |
| DeleteFfElement((FfElement**)&ctx->e2w); |
| DeleteFfElement((FfElement**)&ctx->ea2); |
| Tpm2DeleteContext(&ctx->tpm2_ctx); |
| DeleteEpid2Params(&ctx->epid2_params); |
| DeleteBasenames(&ctx->allowed_basenames); |
| } |
| |
| EpidStatus EpidMemberCreate(MemberParams const* params, MemberCtx** ctx) { |
| size_t context_size = 0; |
| EpidStatus sts = kEpidErr; |
| MemberCtx* member_ctx = NULL; |
| if (!params || !ctx) { |
| return kEpidBadArgErr; |
| } |
| do { |
| sts = EpidMemberGetSize(params, &context_size); |
| BREAK_ON_EPID_ERROR(sts); |
| member_ctx = SAFE_ALLOC(context_size); |
| if (!member_ctx) { |
| BREAK_ON_EPID_ERROR(kEpidMemAllocErr); |
| } |
| sts = EpidMemberInit(params, member_ctx); |
| BREAK_ON_EPID_ERROR(sts); |
| } while (0); |
| if (kEpidNoErr != sts) { |
| SAFE_FREE(member_ctx); |
| member_ctx = NULL; |
| } |
| *ctx = member_ctx; |
| return sts; |
| } |
| |
| EpidStatus EpidMemberInitialProvision(MemberCtx* ctx) { |
| EpidStatus sts = kEpidErr; |
| |
| if (!ctx) { |
| return kEpidBadArgErr; |
| } |
| if (ctx->is_initially_provisioned) { |
| return kEpidOutOfSequenceError; |
| } |
| do { |
| if (ctx->f) { |
| sts = Tpm2LoadExternal(ctx->tpm2_ctx, ctx->f); |
| BREAK_ON_EPID_ERROR(sts); |
| } else { |
| G1ElemStr f; |
| sts = Tpm2CreatePrimary(ctx->tpm2_ctx, &f); |
| BREAK_ON_EPID_ERROR(sts); |
| } |
| |
| ctx->is_initially_provisioned = true; |
| // f value was set into TPM |
| ctx->primary_key_set = true; |
| sts = kEpidNoErr; |
| } while (0); |
| |
| return (sts); |
| } |
| |
| void EpidMemberDelete(MemberCtx** ctx) { |
| if (!ctx) { |
| return; |
| } |
| EpidMemberDeinit(*ctx); |
| SAFE_FREE(*ctx); |
| *ctx = NULL; |
| } |
| |
| EpidStatus EpidMemberSetHashAlg(MemberCtx* ctx, HashAlg hash_alg) { |
| EpidStatus sts = kEpidErr; |
| if (!ctx) return kEpidBadArgErr; |
| if (kSha256 != hash_alg && kSha384 != hash_alg && kSha512 != hash_alg && |
| kSha512_256 != hash_alg) |
| return kEpidBadArgErr; |
| do { |
| sts = Tpm2SetHashAlg(ctx->tpm2_ctx, hash_alg); |
| BREAK_ON_EPID_ERROR(sts); |
| ctx->hash_alg = hash_alg; |
| } while (0); |
| return sts; |
| } |
| |
| EpidStatus EpidMemberSetSigRl(MemberCtx* ctx, SigRl const* sig_rl, |
| size_t sig_rl_size) { |
| if (!ctx || !sig_rl) { |
| return kEpidBadArgErr; |
| } |
| if (!ctx->is_provisioned) { |
| return kEpidOutOfSequenceError; |
| } |
| if (!IsSigRlValid(&ctx->pub_key.gid, sig_rl, sig_rl_size)) { |
| return kEpidBadArgErr; |
| } |
| // Do not set an older version of sig rl |
| if (ctx->sig_rl) { |
| unsigned int current_ver = 0; |
| unsigned int incoming_ver = 0; |
| current_ver = ntohl(ctx->sig_rl->version); |
| incoming_ver = ntohl(sig_rl->version); |
| if (current_ver >= incoming_ver) { |
| return kEpidBadArgErr; |
| } |
| } |
| ctx->sig_rl = sig_rl; |
| |
| return kEpidNoErr; |
| } |
| |
| EpidStatus EpidRegisterBasename(MemberCtx* ctx, void const* basename, |
| size_t basename_len) { |
| EpidStatus sts = kEpidErr; |
| if (basename_len == 0) { |
| return kEpidBadArgErr; |
| } |
| if (!ctx || !basename) { |
| return kEpidBadArgErr; |
| } |
| |
| if (IsBasenameAllowed(ctx->allowed_basenames, basename, basename_len)) { |
| return kEpidDuplicateErr; |
| } |
| |
| sts = AllowBasename(ctx->allowed_basenames, basename, basename_len); |
| |
| return sts; |
| } |
| |
| EpidStatus EpidClearRegisteredBasenames(MemberCtx* ctx) { |
| EpidStatus sts = kEpidErr; |
| if (!ctx) { |
| return kEpidBadArgErr; |
| } |
| DeleteBasenames(&ctx->allowed_basenames); |
| sts = CreateBasenames(&ctx->allowed_basenames); |
| return sts; |
| } |