/*############################################################################
# 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 Epid11VerifyBasicSig implementation.
*/
#include <stdio.h>
#include <string.h>
#include "epid/common/math/src/bignum-internal.h"
#include "epid/common/src/memory.h"
#include "epid/verifier/1.1/api.h"
#include "epid/verifier/1.1/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]))
/// Convert bit size into 32-bit words
#ifndef BITS2BYTES
#define BITS2BYTES(n) ((((n) + 7) / 8))
#endif
/// The EPID11 "sf" value must never be larger than 2**593
#define EPID11_SF_MAX_SIZE_BITS (593)
EpidStatus Epid11VerifyBasicSig(Epid11VerifierCtx const* ctx,
Epid11BasicSignature const* sig,
void const* msg, size_t msg_len) {
EpidStatus res = kEpidNoErr;
// Epid11 G1 elements
EcPoint* T1 = NULL;
EcPoint* T2 = NULL;
EcPoint* R1 = NULL;
EcPoint* R2 = NULL;
EcPoint* t1 = NULL;
EcPoint* t2 = NULL;
// Epid11 GT elements
FfElement* R4 = NULL;
FfElement* t3 = NULL;
// Epid11 G3 elements
EcPoint* B = NULL;
EcPoint* K = NULL;
EcPoint* R3 = NULL;
EcPoint* t5 = NULL;
BigNum* c_bn = NULL;
BigNum* sa_bn = NULL;
BigNum* sb_bn = NULL;
BigNum* nc_bn = NULL;
BigNum* salpha_bn = NULL;
BigNum* sbeta_bn = NULL;
BigNum* nsx_bn = NULL;
BigNum* sf_bn = NULL;
BigNum* sf_tick_bn = NULL;
BigNum* nc_tick_bn = NULL;
BigNum* syalpha_bn = NULL;
Sha256Digest c_hash = {0};
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 (msg_len > UINT_MAX) return kEpidBadArgErr;
if (!ctx->epid11_params || !ctx->pub_key) return kEpidBadArgErr;
do {
bool cmp_result = false;
BigNumStr nc_str = {0};
// handy shorthands:
EcGroup* G1 = ctx->epid11_params->G1;
EcGroup* G3 = ctx->epid11_params->G3;
FiniteField* GT = ctx->epid11_params->GT;
BigNum* p_bn = ctx->epid11_params->p;
BigNum* p_tick_bn = ctx->epid11_params->p_tick;
EcPoint* g1 = ctx->epid11_params->g1;
EcPoint* g2 = ctx->epid11_params->g2;
EcPoint* w = ctx->pub_key->w;
Epid11CommitValues commit_values = ctx->commit_values;
EcPoint* basename_hash = ctx->basename_hash;
if (!G1 || !G3 || !GT || !p_bn || !p_tick_bn || !g1 || !g2 || !w) {
res = kEpidBadArgErr;
BREAK_ON_EPID_ERROR(res);
}
// 1. We use the following variables T1, T2, R1, R2, t1,
// t2 (elements of G1), R4, t3 (elements of GT), B, K, R3,
// t5 (elements of G3), c, sx, sy, sa, sb, salpha, sbeta,
// nc, nc_tick, nsx, syalpha, t4 (256-bit big integers),
// nd (80-bit big integer), and sf (600-bit big integer).
res = NewEcPoint(G1, &T1);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G1, &T2);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G1, &R1);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G1, &R2);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G1, &t1);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G1, &t2);
BREAK_ON_EPID_ERROR(res);
res = NewFfElement(GT, &R4);
BREAK_ON_EPID_ERROR(res);
res = NewFfElement(GT, &t3);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G3, &B);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G3, &K);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G3, &R3);
BREAK_ON_EPID_ERROR(res);
res = NewEcPoint(G3, &t5);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr), &c_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr), &sa_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr), &sb_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr), &nc_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr), &salpha_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr), &sbeta_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr), &nsx_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(OctStr600), &sf_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(OctStr600), &sf_tick_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr), &nc_tick_bn);
BREAK_ON_EPID_ERROR(res);
res = NewBigNum(sizeof(FpElemStr) * 2, &syalpha_bn);
BREAK_ON_EPID_ERROR(res);
// Steps 2-6 done in Epid11Create
// 8. If bsnSize = 0, the verifier verifies G3.inGroup(B) = true.
res = ReadEcPoint(G3, &(sig->B), sizeof(sig->B), B);
if (kEpidNoErr != res) {
if (ctx->basename_len == 0 && kEpidBadArgErr == res) {
res = kEpidSigInvalid;
}
break;
}
// 7. The verifier verifies that G3.isIdentity(B) is false
res = EcIsIdentity(G3, B, &cmp_result);
BREAK_ON_EPID_ERROR(res);
if (cmp_result != false) {
res = kEpidSigInvalid;
break;
}
// 9. If bsnSize > 0, the verifier verifies B = G3.hash(bsn).
if (basename_hash) {
res = EcIsEqual(G3, basename_hash, B, &cmp_result);
BREAK_ON_EPID_ERROR(res);
if (cmp_result != true) {
res = kEpidSigInvalid;
break;
}
}
// 10. The verifier verifies G3.inGroup(K) = true.
res = ReadEcPoint(G3, &(sig->K), sizeof(sig->K), K);
if (kEpidNoErr != res) {
if (kEpidBadArgErr == res) {
res = kEpidSigInvalid;
}
break;
}
// 11. The verifier verifies G1.inGroup(T1) = true.
res = ReadEcPoint(G1, &(sig->T1), sizeof(sig->T1), T1);
if (kEpidNoErr != res) {
if (kEpidBadArgErr == res) {
res = kEpidSigInvalid;
}
break;
}
// 12. The verifier verifies G1.inGroup(T2) = true.
res = ReadEcPoint(G1, &(sig->T2), sizeof(sig->T2), T2);
if (kEpidNoErr != res) {
if (kEpidBadArgErr == res) {
res = kEpidSigInvalid;
}
break;
}
// 13. The verifier verifies sx, sy, sa, sb, salpha, sbeta in [0, p-1].
if (memcmp(&sig->sx, &ctx->commit_values.p, sizeof(FpElemStr)) >= 0 ||
memcmp(&sig->sy, &ctx->commit_values.p, sizeof(FpElemStr)) >= 0 ||
memcmp(&sig->sa, &ctx->commit_values.p, sizeof(FpElemStr)) >= 0 ||
memcmp(&sig->sb, &ctx->commit_values.p, sizeof(FpElemStr)) >= 0 ||
memcmp(&sig->salpha, &ctx->commit_values.p, sizeof(FpElemStr)) >= 0 ||
memcmp(&sig->sbeta, &ctx->commit_values.p, sizeof(FpElemStr)) >= 0) {
res = kEpidSigInvalid;
break;
}
// 14. The verifier verifies that sf is an (at-most) 593-bit unsigned
// integer, in other words, sf < 2**593.
if (EPID11_SF_MAX_SIZE_BITS <=
OctStrBitSize(sig->sf.data, sizeof(sig->sf.data))) {
res = kEpidSigInvalid;
break;
}
// 15. The verifier computes nc = (-c) mod p.
res = ReadBigNum(&(sig->c), sizeof(sig->c), c_bn);
BREAK_ON_EPID_ERROR(res);
res = BigNumMod(c_bn, p_bn, nc_bn);
BREAK_ON_EPID_ERROR(res);
// (-c) mod p == p - (c mod p)
res = BigNumSub(p_bn, nc_bn, nc_bn);
BREAK_ON_EPID_ERROR(res);
// 16. The verifier computes nc_tick = (-c) mod p_tick.
res = BigNumMod(c_bn, p_tick_bn, nc_tick_bn);
BREAK_ON_EPID_ERROR(res);
res = BigNumSub(p_tick_bn, nc_tick_bn, nc_tick_bn);
BREAK_ON_EPID_ERROR(res);
// 17. The verifier computes nsx = (-sx) mod p.
res = ReadBigNum(&(sig->sx), sizeof(sig->sx), nsx_bn);
BREAK_ON_EPID_ERROR(res);
res = BigNumSub(p_bn, nsx_bn, nsx_bn);
BREAK_ON_EPID_ERROR(res);
// 18. The verifier computes syalpha = (sy + salpha) mod p.
res = ReadBigNum(&(sig->salpha), sizeof(sig->salpha), salpha_bn);
BREAK_ON_EPID_ERROR(res);
res = ReadBigNum(&(sig->sy), sizeof(sig->sy), syalpha_bn);
BREAK_ON_EPID_ERROR(res);
res = BigNumAdd(salpha_bn, syalpha_bn, syalpha_bn);
BREAK_ON_EPID_ERROR(res);
res = BigNumMod(syalpha_bn, p_bn, syalpha_bn);
BREAK_ON_EPID_ERROR(res);
// 19. The verifier computes R1 = G1.multiexp(h1, sa, h2, sb, T2, nc).
res = ReadBigNum(&sig->sa, sizeof(sig->sa), sa_bn);
BREAK_ON_EPID_ERROR(res);
res = ReadBigNum(&sig->sb, sizeof(sig->sb), sb_bn);
BREAK_ON_EPID_ERROR(res);
{
EcPoint const* points[3];
BigNum const* exponents[3];
points[0] = ctx->pub_key->h1;
points[1] = ctx->pub_key->h2;
points[2] = T2;
exponents[0] = sa_bn;
exponents[1] = sb_bn;
exponents[2] = nc_bn;
res = EcMultiExpBn(G1, points, exponents, COUNT_OF(points), R1);
BREAK_ON_EPID_ERROR(res);
}
// 20. The verifier computes
// R2 = G1.multiexp(h1, salpha, h2, sbeta, T2, nsx).
res = ReadBigNum(&sig->sbeta, sizeof(sig->sbeta), sbeta_bn);
BREAK_ON_EPID_ERROR(res);
{
EcPoint const* points[3];
BigNum const* exponents[3];
points[0] = ctx->pub_key->h1;
points[1] = ctx->pub_key->h2;
points[2] = T2;
exponents[0] = salpha_bn;
exponents[1] = sbeta_bn;
exponents[2] = nsx_bn;
res = EcMultiExpBn(G1, points, exponents, COUNT_OF(points), R2);
BREAK_ON_EPID_ERROR(res);
}
// 21. The verifier computes R3 = G3.multiexp(B, sf, K, nc_tick).
res = ReadBigNum(&sig->sf, sizeof(sig->sf), sf_tick_bn);
BREAK_ON_EPID_ERROR(res);
// G3.exp(B, sf) = G3(B, sf mod G3.order)
res = BigNumMod(sf_tick_bn, p_tick_bn, sf_tick_bn);
BREAK_ON_EPID_ERROR(res);
{
EcPoint const* points[2];
BigNum const* exponents[2];
points[0] = B;
points[1] = K;
exponents[0] = sf_tick_bn;
exponents[1] = nc_tick_bn;
res = EcMultiExpBn(G3, points, exponents, COUNT_OF(points), R3);
BREAK_ON_EPID_ERROR(res);
}
// 22. The verifier computes t1 = G1.multiexp(T1, nsx, g1, c).
res = BigNumMod(c_bn, p_bn, c_bn);
BREAK_ON_EPID_ERROR(res);
{
EcPoint const* points[2];
BigNum const* exponents[2];
points[0] = T1;
points[1] = g1;
exponents[0] = nsx_bn;
exponents[1] = c_bn;
res = EcMultiExpBn(G1, points, exponents, COUNT_OF(points), t1);
BREAK_ON_EPID_ERROR(res);
}
// 23. The verifier computes t2 = G1.exp(T1, nc).
res = WriteBigNum(nc_bn, sizeof(nc_str), &nc_str);
BREAK_ON_EPID_ERROR(res);
res = EcExp(G1, T1, &nc_str, t2);
BREAK_ON_EPID_ERROR(res);
// 24. The verifier computes R4 = pairing(t1, g2).
res = Epid11Pairing(ctx->epid11_params->pairing_state, t1, g2, R4);
BREAK_ON_EPID_ERROR(res);
// 25. The verifier computes t3 = pairing(t2, w).
res = Epid11Pairing(ctx->epid11_params->pairing_state, t2, w, t3);
BREAK_ON_EPID_ERROR(res);
// 26. The verifier computes R4 = GT.mul(R4, t3).
res = FfMul(GT, R4, t3, R4);
BREAK_ON_EPID_ERROR(res);
// 27. The verifier compute
// t3 = GT.multiexp(e12, sf, e22, syalpha, e2w, sa).
res = ReadBigNum(&sig->sf, sizeof(sig->sf), sf_bn);
BREAK_ON_EPID_ERROR(res);
{
FfElement const* points[3];
BigNum const* exponents[3];
points[0] = ctx->e12;
points[1] = ctx->e22;
points[2] = ctx->e2w;
exponents[0] = sf_bn;
exponents[1] = syalpha_bn;
exponents[2] = sa_bn;
res = FfMultiExpBn(GT, points, exponents, COUNT_OF(points), t3);
BREAK_ON_EPID_ERROR(res);
}
// 28. The verifier compute R4 = GT.mul(R4, t3).
res = FfMul(GT, R4, t3, R4);
BREAK_ON_EPID_ERROR(res);
// 29. The verifier compute t4 = Hash(p || g1 || g2 || g3 || h1 || h2 || w
// || B || K || T1 || T2 || R1 || R2 || R3 || R4).
// 30. The verifier verifies c = H(t4 || nd || mSize || m).
res = SetCalculatedEpid11CommitValues(&sig->B, &sig->K, &sig->T1, &sig->T2,
R1, R2, R3, R4, G1, G3, GT,
&commit_values);
BREAK_ON_EPID_ERROR(res);
res = CalculateEpid11CommitmentHash(&commit_values, msg, (uint32_t)msg_len,
&sig->nd, &c_hash);
BREAK_ON_EPID_ERROR(res);
if (0 != memcmp(&sig->c, &c_hash, sizeof(sig->c))) {
res = kEpidSigInvalid;
break;
}
res = kEpidNoErr;
} while (0);
EpidZeroMemory(&c_hash, sizeof(c_hash));
DeleteEcPoint(&T1);
DeleteEcPoint(&T2);
DeleteEcPoint(&R1);
DeleteEcPoint(&R2);
DeleteEcPoint(&t1);
DeleteEcPoint(&t2);
DeleteFfElement(&R4);
DeleteFfElement(&t3);
DeleteEcPoint(&B);
DeleteEcPoint(&K);
DeleteEcPoint(&R3);
DeleteEcPoint(&t5);
DeleteBigNum(&c_bn);
DeleteBigNum(&sa_bn);
DeleteBigNum(&sb_bn);
DeleteBigNum(&nc_bn);
DeleteBigNum(&salpha_bn);
DeleteBigNum(&sbeta_bn);
DeleteBigNum(&nsx_bn);
DeleteBigNum(&sf_bn);
DeleteBigNum(&sf_tick_bn);
DeleteBigNum(&nc_tick_bn);
DeleteBigNum(&syalpha_bn);
return (res);
}