/*############################################################################ # 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 Epid11Verify implementation. */ #include <string.h> #include "epid/common/src/endian_convert.h" #include "epid/verifier/1.1/api.h" #include "epid/verifier/1.1/src/context.h" static size_t Epid11GetSignatureRlCount(Epid11Signature const* sig) { return (!sig) ? 0 : ntohl(sig->n2); } static size_t Epid11GetGroupRlCount(Epid11GroupRl const* rl) { return (!rl) ? 0 : ntohl(rl->n3); } static size_t Epid11GetSigRlCount(Epid11SigRl const* rl) { return (!rl) ? 0 : ntohl(rl->n2); } static size_t Epid11GetPrivRlCount(Epid11PrivRl const* rl) { return (!rl) ? 0 : ntohl(rl->n1); } /// Check PrivRL status of a signature for one PrivRl entry /*! computes t5 =G3.exp(B, f[i]) and verifies that G3.isEqual(t5, K) = false. \param[in] ctx The verifier context. \param[in] sig The basic signature. \param[in] f_str priv_rl entry to check. \returns ::EpidStatus \retval ::kEpidNoErr Signature was not revoked \retval ::kEpidSigRevokedInPrivRl Signature revoked in PrivRl */ EpidStatus Epid11PrVerify(Epid11VerifierCtx const* ctx, Epid11BasicSignature const* sig, BigNumStr* f_str) { EpidStatus sts = kEpidErr; EcPoint* B = NULL; EcPoint* K = NULL; EcPoint* t5 = NULL; FfElement* f = NULL; EcGroup* G3 = ctx->epid11_params->G3; FiniteField* Fp = ctx->epid11_params->Fp; bool eq = false; do { sts = NewFfElement(Fp, &f); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } sts = NewEcPoint(G3, &B); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } sts = NewEcPoint(G3, &K); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } sts = NewEcPoint(G3, &t5); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } // ReadFfElement checks that the value f_str is in the field sts = ReadFfElement(Fp, f_str, sizeof(BigNumStr), f); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } sts = ReadEcPoint(G3, &sig->B, sizeof(sig->B), B); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } sts = ReadEcPoint(G3, &sig->K, sizeof(sig->K), K); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } sts = EcExp(G3, B, f_str, t5); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } sts = EcIsEqual(G3, t5, K, &eq); if (kEpidNoErr != sts) { sts = kEpidMathErr; break; } if (eq) { sts = kEpidSigRevokedInPrivRl; } else { sts = kEpidNoErr; } } while (0); DeleteFfElement(&f); DeleteEcPoint(&t5); DeleteEcPoint(&K); DeleteEcPoint(&B); return sts; } EpidStatus Epid11Verify(Epid11VerifierCtx const* ctx, Epid11Signature const* sig, size_t sig_len, void const* msg, size_t msg_len) { // Step 1. Setup size_t const sig_header_len = (sizeof(Epid11Signature) - sizeof(Epid11NrProof)); EpidStatus sts = kEpidErr; size_t rl_count = 0; size_t i; if (!sig || !ctx || !ctx->epid11_params || !ctx->pub_key) { return kEpidBadArgErr; } if (!msg && (0 != msg_len)) { // if message is non-empty it must have both length and content return kEpidBadArgErr; } if (sig_len < sig_header_len) { return kEpidBadArgErr; } rl_count = Epid11GetSignatureRlCount(sig); if (rl_count > (SIZE_MAX - sig_header_len) / sizeof(sig->sigma[0]) || (rl_count * sizeof(sig->sigma[0])) + sig_header_len != sig_len) { return kEpidBadArgErr; } // Check if signature has NrPoofs but SigRl is not set if (0 < rl_count && !ctx->sig_rl) { return kEpidBadArgErr; } // Step 3. The verifier verifies gid in the public key, PRIV-RL, and // SIG-RL (if provided) and the verifier pre-computation blob all match. if (ctx->priv_rl) { if (0 != memcmp(&ctx->pub_key->gid, &ctx->priv_rl->gid, sizeof(ctx->pub_key->gid))) { return kEpidBadArgErr; } } if (ctx->sig_rl) { if (0 != memcmp(&ctx->pub_key->gid, &ctx->sig_rl->gid, sizeof(ctx->pub_key->gid))) { return kEpidBadArgErr; } } // Verification of gid value in precomputation blob // and public key is done in ReadPrecomp // Step 4. The verifier verifies the signatures of PRIV-RL, // SIG-RL (if provided), and Group-RL (if provided) using IVK. // Data is already verified. // Step 5. If GroupRL is provided as input,... if (ctx->group_rl) { // ...the verifier verifies that gid has not been revoked, i.e., // gid does not match any entry in Group-RL. size_t grouprl_count = Epid11GetGroupRlCount(ctx->group_rl); for (i = 0; i < grouprl_count; ++i) { if (0 == memcmp(&ctx->pub_key->gid, &ctx->group_rl->gid[i], sizeof(ctx->pub_key->gid))) { return kEpidSigRevokedInGroupRl; } } } // Step 6. If SIG-RL is provided as input,... if (ctx->sig_rl) { size_t sigrl_count = Epid11GetSigRlCount(ctx->sig_rl); // ...the verifier verifies that RLver and n2 // values in s match with the values in SIG-RL.... if (0 != memcmp(&ctx->sig_rl->version, &sig->rl_ver, sizeof(ctx->sig_rl->version))) { return kEpidErr; } if (sigrl_count != rl_count) { return kEpidBadArgErr; } } // Step 7-30. The verifier verifies the basic signature. sts = Epid11VerifyBasicSig(ctx, &sig->sigma0, msg, msg_len); if (sts != kEpidNoErr) { return kEpidSigInvalid; } // Step 31. For i = 0, ..., n1-1, the verifier computes t5 =G3.exp(B, f[i]) // and verifies that G3.isEqual(t5, K) = false. if (ctx->priv_rl) { size_t privrl_count = Epid11GetPrivRlCount(ctx->priv_rl); for (i = 0; i < privrl_count; ++i) { sts = Epid11PrVerify(ctx, &sig->sigma0, (BigNumStr*)&ctx->priv_rl->f[i]); if (sts != kEpidNoErr) { return kEpidSigRevokedInPrivRl; } } } // Step 32. For i = 0, ..., n2-1, the verifier verifies nrVerify(B, K, B[i], // K[i], Sigma[i]) = true. The details of nrVerify() will be given in the // next subsection. if (ctx->sig_rl) { size_t sigrl_count = Epid11GetSigRlCount(ctx->sig_rl); for (i = 0; i < sigrl_count; ++i) { sts = Epid11NrVerify(ctx, &sig->sigma0, msg, msg_len, &ctx->sig_rl->bk[i], &sig->sigma[i]); if (sts != kEpidNoErr) { return kEpidSigRevokedInSigRl; } } } // Step 33. If all the above verifications succeed, the verifier outputs true. return kEpidSigValid; }