| /*############################################################################ |
| # 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 Intel Intel(R) EPID 1.1 Verifier context implementation. |
| */ |
| |
| #include "epid/verifier/1.1/src/context.h" |
| #include "epid/common/src/endian_convert.h" |
| #include "epid/common/src/memory.h" |
| #include "epid/verifier/1.1/api.h" |
| |
| /// Handle SDK Error with Break |
| #define BREAK_ON_EPID_ERROR(ret) \ |
| \ |
| if (kEpidNoErr != (ret)) { \ |
| break; \ |
| } |
| |
| /// create Verifier precomp of the Epid11VerifierCtx |
| static EpidStatus DoPrecomputation(Epid11VerifierCtx* ctx); |
| |
| /// Read Verifier precomp |
| static EpidStatus ReadPrecomputation(Epid11VerifierPrecomp const* precomp_str, |
| Epid11VerifierCtx* ctx); |
| |
| /// Internal function to prove if group based revocation list is valid |
| static bool Epid11IsGroupRlValid(Epid11GroupRl const* group_rl, |
| size_t grp_rl_size) { |
| const size_t kMinGroupRlSize = sizeof(Epid11GroupRl) - sizeof(Epid11GroupId); |
| size_t input_grp_rl_size = 0; |
| |
| if (!group_rl) { |
| return false; |
| } |
| if (grp_rl_size < kMinGroupRlSize) { |
| return false; |
| } |
| if (ntohl(group_rl->n3) > |
| (SIZE_MAX - kMinGroupRlSize) / sizeof(Epid11GroupId)) { |
| return false; |
| } |
| input_grp_rl_size = |
| kMinGroupRlSize + (ntohl(group_rl->n3) * sizeof(Epid11GroupId)); |
| if (input_grp_rl_size != grp_rl_size) { |
| return false; |
| } |
| return true; |
| } |
| /// Internal function to prove if signature based revocation list is valid |
| bool Epid11IsSigRlValid(Epid11GroupId const* gid, Epid11SigRl const* sig_rl, |
| size_t sig_rl_size) { |
| const size_t kMinSigRlSize = sizeof(Epid11SigRl) - sizeof(Epid11SigRlEntry); |
| size_t input_sig_rl_size = 0; |
| if (!gid || !sig_rl || kMinSigRlSize > sig_rl_size) { |
| return false; |
| } |
| if (ntohl(sig_rl->n2) > (SIZE_MAX - kMinSigRlSize) / sizeof(sig_rl->bk[0])) { |
| return false; |
| } |
| // sanity check of intput SigRl size |
| input_sig_rl_size = kMinSigRlSize + ntohl(sig_rl->n2) * sizeof(sig_rl->bk[0]); |
| if (input_sig_rl_size != sig_rl_size) { |
| return false; |
| } |
| // verify that gid given and gid in SigRl match |
| if (0 != memcmp(gid, &sig_rl->gid, sizeof(*gid))) { |
| return false; |
| } |
| return true; |
| } |
| /// Internal function to verify if Intel(R) EPID 1.1 private key based |
| /// revocation list is valid |
| static bool IsEpid11PrivRlValid(Epid11GroupId const* gid, |
| Epid11PrivRl const* priv_rl, |
| size_t priv_rl_size) { |
| const size_t kMinPrivRlSize = sizeof(Epid11PrivRl) - sizeof(FpElemStr); |
| size_t input_priv_rl_size = 0; |
| |
| if (!gid || !priv_rl || kMinPrivRlSize > priv_rl_size) { |
| return false; |
| } |
| if (ntohl(priv_rl->n1) > |
| (SIZE_MAX - kMinPrivRlSize) / sizeof(priv_rl->f[0])) { |
| return false; |
| } |
| // sanity check of input Epid11PrivRl size |
| input_priv_rl_size = |
| kMinPrivRlSize + ntohl(priv_rl->n1) * sizeof(priv_rl->f[0]); |
| if (input_priv_rl_size != priv_rl_size) { |
| return false; |
| } |
| // verify that gid given and gid in Epid11PrivRl match |
| if (0 != memcmp(gid, &priv_rl->gid, sizeof(*gid))) { |
| return false; |
| } |
| return true; |
| } |
| |
| EpidStatus Epid11VerifierCreate(Epid11GroupPubKey const* pub_key, |
| Epid11VerifierPrecomp const* precomp, |
| Epid11VerifierCtx** ctx) { |
| EpidStatus result = kEpidErr; |
| Epid11VerifierCtx* verifier_ctx = NULL; |
| if (!pub_key || !ctx) { |
| return kEpidBadArgErr; |
| } |
| do { |
| // Allocate memory for VerifierCtx |
| verifier_ctx = SAFE_ALLOC(sizeof(Epid11VerifierCtx)); |
| if (!verifier_ctx) { |
| result = kEpidMemAllocErr; |
| break; |
| } |
| |
| // Internal representation of Epid11Params |
| result = CreateEpid11Params(&verifier_ctx->epid11_params); |
| BREAK_ON_EPID_ERROR(result); |
| // Internal representation of Group Pub Key |
| result = CreateEpid11GroupPubKey(pub_key, verifier_ctx->epid11_params->G1, |
| verifier_ctx->epid11_params->G2, |
| &verifier_ctx->pub_key); |
| BREAK_ON_EPID_ERROR(result); |
| // Store group public key strings for later use |
| result = |
| SetKeySpecificEpid11CommitValues(pub_key, &verifier_ctx->commit_values); |
| if (kEpidNoErr != result) { |
| break; |
| } |
| // Allocate verifier_ctx->e12 |
| result = NewFfElement(verifier_ctx->epid11_params->GT, &verifier_ctx->e12); |
| BREAK_ON_EPID_ERROR(result); |
| // Allocate verifier_ctx->e22 |
| result = NewFfElement(verifier_ctx->epid11_params->GT, &verifier_ctx->e22); |
| BREAK_ON_EPID_ERROR(result); |
| // Allocate verifier_ctx->e2w |
| result = NewFfElement(verifier_ctx->epid11_params->GT, &verifier_ctx->e2w); |
| BREAK_ON_EPID_ERROR(result); |
| // precomputation |
| if (precomp != NULL) { |
| result = ReadPrecomputation(precomp, verifier_ctx); |
| } else { |
| result = DoPrecomputation(verifier_ctx); |
| } |
| BREAK_ON_EPID_ERROR(result); |
| verifier_ctx->sig_rl = NULL; |
| verifier_ctx->group_rl = NULL; |
| verifier_ctx->priv_rl = NULL; |
| *ctx = verifier_ctx; |
| result = kEpidNoErr; |
| } while (0); |
| |
| if (kEpidNoErr != result && verifier_ctx) { |
| DeleteFfElement(&verifier_ctx->e2w); |
| DeleteFfElement(&verifier_ctx->e22); |
| DeleteFfElement(&verifier_ctx->e12); |
| DeleteEpid11GroupPubKey(&verifier_ctx->pub_key); |
| DeleteEpid11Params(&verifier_ctx->epid11_params); |
| SAFE_FREE(verifier_ctx); |
| } |
| return result; |
| } |
| |
| void Epid11VerifierDelete(Epid11VerifierCtx** ctx) { |
| if (ctx && *ctx) { |
| DeleteFfElement(&(*ctx)->e2w); |
| DeleteFfElement(&(*ctx)->e22); |
| DeleteFfElement(&(*ctx)->e12); |
| DeleteEpid11GroupPubKey(&(*ctx)->pub_key); |
| DeleteEpid11Params(&(*ctx)->epid11_params); |
| (*ctx)->priv_rl = NULL; |
| (*ctx)->sig_rl = NULL; |
| (*ctx)->group_rl = NULL; |
| DeleteEcPoint(&(*ctx)->basename_hash); |
| SAFE_FREE((*ctx)->basename); |
| (*ctx)->basename_len = 0; |
| SAFE_FREE(*ctx); |
| } |
| } |
| |
| EpidStatus Epid11VerifierWritePrecomp(Epid11VerifierCtx const* ctx, |
| Epid11VerifierPrecomp* precomp) { |
| EpidStatus result = kEpidErr; |
| FfElement* e12 = NULL; // an element in GT |
| FfElement* e22 = NULL; // an element in GT |
| FfElement* e2w = NULL; // an element in GT |
| FiniteField* GT = NULL; // Finite field GT(Fq6) |
| if (!ctx || !ctx->e12 || !ctx->e22 || !ctx->e2w || !ctx->epid11_params || |
| !(ctx->epid11_params->GT) || !ctx->pub_key || !precomp) { |
| return kEpidBadArgErr; |
| } |
| e12 = ctx->e12; |
| e22 = ctx->e22; |
| e2w = ctx->e2w; |
| GT = ctx->epid11_params->GT; |
| |
| precomp->gid = ctx->pub_key->gid; |
| result = WriteFfElement(GT, e12, &(precomp->e12), sizeof(precomp->e12)); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| result = WriteFfElement(GT, e22, &(precomp->e22), sizeof(precomp->e22)); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| result = WriteFfElement(GT, e2w, &(precomp->e2w), sizeof(precomp->e2w)); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| return result; |
| } |
| |
| EpidStatus Epid11VerifierSetPrivRl(Epid11VerifierCtx* ctx, |
| Epid11PrivRl const* priv_rl, |
| size_t priv_rl_size) { |
| if (!ctx || !priv_rl || !ctx->pub_key) { |
| return kEpidBadArgErr; |
| } |
| if (!IsEpid11PrivRlValid(&ctx->pub_key->gid, priv_rl, priv_rl_size)) { |
| return kEpidBadArgErr; |
| } |
| // Do not set an older version of Epid11PrivRl |
| if (ctx->priv_rl) { |
| unsigned int current_ver = 0; |
| unsigned int incoming_ver = 0; |
| current_ver = ntohl(ctx->priv_rl->version); |
| incoming_ver = ntohl(priv_rl->version); |
| if (current_ver >= incoming_ver) { |
| return kEpidBadArgErr; |
| } |
| } |
| ctx->priv_rl = priv_rl; |
| return kEpidNoErr; |
| } |
| |
| EpidStatus Epid11VerifierSetSigRl(Epid11VerifierCtx* ctx, |
| Epid11SigRl const* sig_rl, |
| size_t sig_rl_size) { |
| if (!ctx || !sig_rl || !ctx->pub_key) { |
| 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; |
| } |
| } |
| if (!Epid11IsSigRlValid(&ctx->pub_key->gid, sig_rl, sig_rl_size)) { |
| return kEpidBadArgErr; |
| } |
| ctx->sig_rl = sig_rl; |
| |
| return kEpidNoErr; |
| } |
| |
| EpidStatus Epid11VerifierSetGroupRl(Epid11VerifierCtx* ctx, |
| Epid11GroupRl const* grp_rl, |
| size_t grp_rl_size) { |
| if (!ctx || !grp_rl || !ctx->pub_key) { |
| return kEpidBadArgErr; |
| } |
| if (!Epid11IsGroupRlValid(grp_rl, grp_rl_size)) { |
| return kEpidBadArgErr; |
| } |
| // Do not set an older version of group rl |
| if (ctx->group_rl) { |
| unsigned int current_ver = 0; |
| unsigned int incoming_ver = 0; |
| current_ver = ntohl(ctx->group_rl->version); |
| incoming_ver = ntohl(grp_rl->version); |
| if (current_ver >= incoming_ver) { |
| return kEpidBadArgErr; |
| } |
| } |
| ctx->group_rl = grp_rl; |
| |
| return kEpidNoErr; |
| } |
| |
| EpidStatus Epid11VerifierSetBasename(Epid11VerifierCtx* ctx, |
| void const* basename, |
| size_t basename_len) { |
| EpidStatus result = kEpidErr; |
| EcPoint* basename_hash = NULL; |
| uint8_t* basename_buffer = NULL; |
| |
| if (!ctx || !ctx->epid11_params || !ctx->epid11_params->G3) { |
| return kEpidBadArgErr; |
| } |
| if (!basename && basename_len > 0) { |
| return kEpidBadArgErr; |
| } |
| |
| if (!basename) { |
| ctx->basename_len = 0; |
| DeleteEcPoint(&ctx->basename_hash); |
| SAFE_FREE(ctx->basename); |
| return kEpidNoErr; |
| } |
| |
| do { |
| EcGroup* G3 = ctx->epid11_params->G3; |
| result = NewEcPoint(G3, &basename_hash); |
| if (kEpidNoErr != result) { |
| break; |
| } |
| |
| result = Epid11EcHash(G3, basename, basename_len, basename_hash); |
| if (kEpidNoErr != result) { |
| break; |
| } |
| |
| if (basename_len > 0) { |
| basename_buffer = SAFE_ALLOC(basename_len); |
| if (!basename_buffer) { |
| result = kEpidMemAllocErr; |
| break; |
| } |
| } |
| |
| ctx->basename_len = basename_len; |
| |
| if (basename_len > 0) { |
| // memcpy is used to copy variable length basename |
| if (0 != memcpy_S(basename_buffer, ctx->basename_len, basename, |
| basename_len)) { |
| result = kEpidErr; |
| break; |
| } |
| } |
| DeleteEcPoint(&ctx->basename_hash); |
| SAFE_FREE(ctx->basename); |
| ctx->basename = basename_buffer; |
| ctx->basename_hash = basename_hash; |
| |
| result = kEpidNoErr; |
| } while (0); |
| |
| if (kEpidNoErr != result) { |
| DeleteEcPoint(&basename_hash); |
| SAFE_FREE(basename_buffer); |
| } |
| return result; |
| } |
| |
| static EpidStatus DoPrecomputation(Epid11VerifierCtx* ctx) { |
| EpidStatus result = kEpidErr; |
| FfElement* e12 = NULL; |
| FfElement* e22 = NULL; |
| FfElement* e2w = NULL; |
| Epid11Params_* params = NULL; |
| Epid11GroupPubKey_* pub_key = NULL; |
| Epid11PairingState* ps_ctx = NULL; |
| if (!ctx) { |
| return kEpidBadArgErr; |
| } |
| if (!ctx->epid11_params || !ctx->epid11_params->GT || |
| !ctx->epid11_params->pairing_state || !ctx->pub_key || !ctx->e12 || |
| !ctx->e22 || !ctx->e2w) { |
| return kEpidBadArgErr; |
| } |
| pub_key = ctx->pub_key; |
| params = ctx->epid11_params; |
| e12 = ctx->e12; |
| e22 = ctx->e22; |
| e2w = ctx->e2w; |
| ps_ctx = params->pairing_state; |
| // do precomputation |
| // 1. The verifier computes e12 = pairing(h1, g2). |
| result = Epid11Pairing(ps_ctx, pub_key->h1, params->g2, e12); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| // 2. The verifier computes e22 = pairing(h2, g2). |
| result = Epid11Pairing(ps_ctx, pub_key->h2, params->g2, e22); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| // 3. The verifier computes e2w = pairing(h2, w). |
| result = Epid11Pairing(ps_ctx, pub_key->h2, pub_key->w, e2w); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| return kEpidNoErr; |
| } |
| static EpidStatus ReadPrecomputation(Epid11VerifierPrecomp const* precomp_str, |
| Epid11VerifierCtx* ctx) { |
| EpidStatus result = kEpidErr; |
| FfElement* e12 = NULL; |
| FfElement* e22 = NULL; |
| FfElement* e2w = NULL; |
| FiniteField* GT = NULL; |
| Epid11Params_* params = NULL; |
| unsigned int current_gid = 0; |
| unsigned int incoming_gid = 0; |
| if (!ctx) { |
| return kEpidBadArgErr; |
| } |
| if (!ctx->epid11_params || !ctx->epid11_params->GT || !ctx->e12 || |
| !ctx->e22 || !ctx->e2w) { |
| return kEpidBadArgErr; |
| } |
| |
| if (!ctx->pub_key || !precomp_str) return kEpidBadArgErr; |
| |
| current_gid = ntohl(ctx->pub_key->gid); |
| incoming_gid = ntohl(precomp_str->gid); |
| |
| if (current_gid != incoming_gid) { |
| return kEpidBadArgErr; |
| } |
| |
| params = ctx->epid11_params; |
| GT = params->GT; |
| e12 = ctx->e12; |
| e22 = ctx->e22; |
| e2w = ctx->e2w; |
| |
| result = ReadFfElement(GT, &precomp_str->e12, sizeof(precomp_str->e12), e12); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| result = ReadFfElement(GT, &precomp_str->e22, sizeof(precomp_str->e22), e22); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| result = ReadFfElement(GT, &precomp_str->e2w, sizeof(precomp_str->e2w), e2w); |
| if (kEpidNoErr != result) { |
| return result; |
| } |
| return kEpidNoErr; |
| } |