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