/*############################################################################ # 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 VerifyBasicSig implementation. */ #include "epid/common/src/memory.h" #include "epid/verifier/api.h" #include "epid/verifier/src/context.h" /// Handle SDK Error with Break #define BREAK_ON_EPID_ERROR(ret) \ if (kEpidNoErr != (ret)) { \ break; \ } /// Count of elements in array #define COUNT_OF(A) (sizeof(A) / sizeof((A)[0])) EpidStatus EpidVerifyBasicSig(VerifierCtx const* ctx, BasicSignature const* sig, void const* msg, size_t msg_len) { EpidStatus res = kEpidNotImpl; EcPoint* B = NULL; EcPoint* K = NULL; EcPoint* T = NULL; EcPoint* R1 = NULL; EcPoint* t4 = NULL; EcPoint* t1 = NULL; FfElement* R2 = NULL; FfElement* t2 = NULL; FfElement* c = NULL; FfElement* sx = NULL; FfElement* sf = NULL; FfElement* sa = NULL; FfElement* sb = NULL; FfElement* nc = NULL; FfElement* nsx = NULL; FfElement* c_hash = NULL; if (!ctx || !sig) return kEpidBadArgErr; if (!msg && (0 != msg_len)) { // if message is non-empty it must have both length and content return kEpidBadArgErr; } if (!ctx->epid2_params || !ctx->pub_key) return kEpidBadArgErr; do { bool cmp_result = false; BigNumStr c_str = {0}; BigNumStr sf_str = {0}; BigNumStr nc_str = {0}; BigNumStr nsx_str = {0}; BigNumStr sb_str = {0}; BigNumStr sa_str = {0}; // handy shorthands: EcGroup* G1 = ctx->epid2_params->G1; EcGroup* G2 = ctx->epid2_params->G2; FiniteField* GT = ctx->epid2_params->GT; FiniteField* Fp = ctx->epid2_params->Fp; EcPoint* g1 = ctx->epid2_params->g1; EcPoint* g2 = ctx->epid2_params->g2; EcPoint* w = ctx->pub_key->w; CommitValues commit_values = ctx->commit_values; EcPoint* basename_hash = ctx->basename_hash; if (!G1 || !G2 || !GT || !Fp || !g1 || !g2 || !w) { res = kEpidBadArgErr; BREAK_ON_EPID_ERROR(res); } // The following variables B, K, T, R1, t4 (elements of G1), t1 // (element of G2), R2, t2 (elements of GT), c, sx, sf, sa, sb, // nc, nsx, t3 (256-bit integers) are used. res = NewEcPoint(G1, &B); BREAK_ON_EPID_ERROR(res); res = NewEcPoint(G1, &K); BREAK_ON_EPID_ERROR(res); res = NewEcPoint(G1, &T); BREAK_ON_EPID_ERROR(res); res = NewEcPoint(G1, &R1); BREAK_ON_EPID_ERROR(res); res = NewEcPoint(G1, &t4); BREAK_ON_EPID_ERROR(res); res = NewEcPoint(G2, &t1); BREAK_ON_EPID_ERROR(res); res = NewFfElement(GT, &R2); BREAK_ON_EPID_ERROR(res); res = NewFfElement(GT, &t2); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &c); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &sx); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &sf); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &sa); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &sb); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &nc); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &nsx); BREAK_ON_EPID_ERROR(res); res = NewFfElement(Fp, &c_hash); BREAK_ON_EPID_ERROR(res); // 1. The verifier expect pre-computation is done (e12, e22, e2w, // eg12). Refer to Section 3.6 for the computation of these // values. // 2. The verifier verifies the basic signature sigma0 as follows: // a. The verifier verifies G1.inGroup(B) = true. res = ReadEcPoint(G1, &(sig->B), sizeof(sig->B), B); if (kEpidNoErr != res) { if (kEpidBadArgErr == res) { res = kEpidSigInvalid; } break; } // b. The verifier verifies that G1.isIdentity(B) is false. res = EcIsIdentity(G1, B, &cmp_result); BREAK_ON_EPID_ERROR(res); if (cmp_result != false) { res = kEpidSigInvalid; break; } // c. If bsn is provided, the verifier verifies B = // G1.hash(bsn). if (basename_hash) { res = EcIsEqual(G1, basename_hash, B, &cmp_result); BREAK_ON_EPID_ERROR(res); if (cmp_result != true) { res = kEpidSigInvalid; break; } } // d. The verifier verifies G1.inGroup(K) = true. res = ReadEcPoint(G1, &(sig->K), sizeof(sig->K), K); if (kEpidNoErr != res) { if (kEpidBadArgErr == res) { res = kEpidSigInvalid; } break; } // e. The verifier verifies G1.inGroup(T) = true. res = ReadEcPoint(G1, &(sig->T), sizeof(sig->T), T); if (kEpidNoErr != res) { if (kEpidBadArgErr == res) { res = kEpidSigInvalid; } break; } // f. The verifier verifies c, sx, sf, sa, sb in [0, p-1]. res = ReadFfElement(Fp, &(sig->c), sizeof(sig->c), c); if (kEpidNoErr != res) { if (kEpidBadArgErr == res) { res = kEpidSigInvalid; } break; } res = WriteFfElement(Fp, c, &c_str, sizeof(c_str)); BREAK_ON_EPID_ERROR(res); res = ReadFfElement(Fp, &(sig->sx), sizeof(sig->sx), sx); if (kEpidNoErr != res) { if (kEpidBadArgErr == res) { res = kEpidSigInvalid; } break; } res = ReadFfElement(Fp, &(sig->sf), sizeof(sig->sf), sf); if (kEpidNoErr != res) { if (kEpidBadArgErr == res) { res = kEpidSigInvalid; } break; } res = ReadFfElement(Fp, &(sig->sa), sizeof(sig->sa), sa); if (kEpidNoErr != res) { if (kEpidBadArgErr == res) { res = kEpidSigInvalid; } break; } res = ReadFfElement(Fp, &(sig->sb), sizeof(sig->sb), sb); if (kEpidNoErr != res) { if (kEpidBadArgErr == res) { res = kEpidSigInvalid; } break; } // g. The verifier computes nc = (-c) mod p. res = FfNeg(Fp, c, nc); BREAK_ON_EPID_ERROR(res); // h. The verifier computes nsx = (-sx) mod p. res = FfNeg(Fp, sx, nsx); BREAK_ON_EPID_ERROR(res); // i. The verifier computes R1 = G1.multiExp(B, sf, K, nc). res = WriteFfElement(Fp, sf, &sf_str, sizeof(sf_str)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, nc, &nc_str, sizeof(nc_str)); BREAK_ON_EPID_ERROR(res); { EcPoint const* points[2]; BigNumStr const* exponents[2]; points[0] = B; points[1] = K; exponents[0] = &sf_str; exponents[1] = &nc_str; res = EcMultiExp(G1, points, exponents, COUNT_OF(points), R1); BREAK_ON_EPID_ERROR(res); } // j. The verifier computes t1 = G2.multiExp(g2, nsx, w, nc). res = WriteFfElement(Fp, nsx, &nsx_str, sizeof(nsx_str)); BREAK_ON_EPID_ERROR(res); { EcPoint const* points[2]; BigNumStr const* exponents[2]; points[0] = g2; points[1] = w; exponents[0] = &nsx_str; exponents[1] = &nc_str; res = EcMultiExp(G2, points, exponents, COUNT_OF(points), t1); BREAK_ON_EPID_ERROR(res); } // k. The verifier computes R2 = pairing(T, t1). res = Pairing(ctx->epid2_params->pairing_state, T, t1, R2); BREAK_ON_EPID_ERROR(res); // l. The verifier compute t2 = GT.multiExp(e12, sf, e22, sb, // e2w, sa, eg12, c). res = WriteFfElement(Fp, sb, &sb_str, sizeof(sb_str)); BREAK_ON_EPID_ERROR(res); res = WriteFfElement(Fp, sa, &sa_str, sizeof(sa_str)); BREAK_ON_EPID_ERROR(res); { FfElement const* points[4]; BigNumStr const* exponents[4]; points[0] = ctx->e12; points[1] = ctx->e22; points[2] = ctx->e2w; points[3] = ctx->eg12; exponents[0] = &sf_str; exponents[1] = &sb_str; exponents[2] = &sa_str; exponents[3] = &c_str; res = FfMultiExp(GT, points, exponents, COUNT_OF(points), t2); BREAK_ON_EPID_ERROR(res); } // m. The verifier compute R2 = GT.mul(R2, t2). res = FfMul(GT, R2, t2, R2); BREAK_ON_EPID_ERROR(res); // n. The verifier compute t3 = Fp.hash(p || g1 || g2 || h1 || // h2 || w || B || K || T || R1 || R2). // o. The verifier verifies c = Fp.hash(t3 || m). res = SetCalculatedCommitValues(&sig->B, &sig->K, &sig->T, R1, G1, R2, GT, &commit_values); BREAK_ON_EPID_ERROR(res); res = CalculateCommitmentHash(&commit_values, Fp, ctx->hash_alg, msg, msg_len, c_hash); BREAK_ON_EPID_ERROR(res); res = FfIsEqual(Fp, c, c_hash, &cmp_result); BREAK_ON_EPID_ERROR(res); if (cmp_result != true) { // p. If any of the above verifications fails, the verifier // aborts and outputs 1. res = kEpidSigInvalid; break; } res = kEpidNoErr; } while (0); DeleteEcPoint(&B); DeleteEcPoint(&K); DeleteEcPoint(&T); DeleteEcPoint(&R1); DeleteEcPoint(&t4); DeleteEcPoint(&t1); DeleteFfElement(&R2); DeleteFfElement(&t2); DeleteFfElement(&c); DeleteFfElement(&sx); DeleteFfElement(&sf); DeleteFfElement(&sa); DeleteFfElement(&sb); DeleteFfElement(&nc); DeleteFfElement(&nsx); DeleteFfElement(&c_hash); return (res); }