/*############################################################################
# Copyright 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.
############################################################################*/
/// Tiny EpidNrProve implementation.
/*! \file */
#include "epid/member/tiny/src/nrprove.h"
#include "epid/common/errors.h"
#include "epid/member/tiny/math/efq.h"
#include "epid/member/tiny/math/fp.h"
#include "epid/member/tiny/math/hashwrap.h"
#include "epid/member/tiny/math/mathtypes.h"
#include "epid/member/tiny/math/serialize.h"
#include "epid/member/tiny/src/context.h"
#include "epid/member/tiny/src/native_types.h"
static const FpElem epid20_p = {
{{0xD10B500D, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E,
0xFFFCF0CD, 0xFFFFFFFF}}};
static const EccPointFq epid20_g1 = {
{{{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000}}},
{{{0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000}}}};
EpidStatus EpidNrProve(MemberCtx const* ctx, void const* msg, size_t msg_len,
NativeBasicSignature const* sig,
SigRlEntry const* sigrl_entry, NrProof* proof) {
EpidStatus sts = kEpidBadArgErr;
FpElem mu;
FpElem rmu;
FpElem smu;
FpElem nu;
FpElem rnu;
FpElem snu;
EccPointFq tmp_efq;
EccPointFq B_tick;
EccPointFq K_tick;
BigNumStr p;
G1ElemStr tmp_str;
G1ElemStr T_str;
G1ElemStr R1_str;
G1ElemStr R2_str;
FpElem c;
tiny_sha sha_state;
sha_digest digest;
EFqDeserialize(&B_tick, &sigrl_entry->b);
EFqDeserialize(&K_tick, &sigrl_entry->k);
if (!EFqOnCurve(&B_tick) || !EFqOnCurve(&K_tick) || !EFqOnCurve(&sig->B) ||
!EFqOnCurve(&sig->K)) {
return kEpidBadArgErr;
}
// 1. The member chooses random mu from [1, p-1].
if (!FpRandNonzero(&mu, ctx->rnd_func, ctx->rnd_param)) {
return kEpidMathErr;
}
// 2. The member computes nu = (- f * mu) mod p.
FpNeg(&rmu, &ctx->f);
FpMul(&nu, &rmu, &mu);
do {
// 3. The member computes T = G1.sscmMultiExp(K', mu, B', nu). If
// G1.isIdentity(T) = true, the member also outputs "failed".
if (!EFqAffineMultiExp(&tmp_efq, &K_tick, &mu, &B_tick, &nu)) {
sts = kEpidSigRevokedInSigRl;
break;
}
EFqSerialize(&T_str, &tmp_efq);
// 4. The member chooses rmu, rnu randomly from[1, p - 1].
if (!FpRandNonzero(&rmu, ctx->rnd_func, ctx->rnd_param)) {
sts = kEpidMathErr;
break;
}
if (!FpRandNonzero(&rnu, ctx->rnd_func, ctx->rnd_param)) {
sts = kEpidMathErr;
break;
}
// 5. The member computes R1 = G1.sscmMultiExp(K, rmu, B, rnu).
if (!EFqAffineMultiExp(&tmp_efq, &sig->K, &rmu, &sig->B, &rnu)) {
break;
}
EFqSerialize(&R1_str, &tmp_efq);
// 6. The member computes R2 = G1.sscmMultiExp(K', rmu, B', rnu).
if (!EFqAffineMultiExp(&tmp_efq, &K_tick, &rmu, &B_tick, &rnu)) {
break;
}
EFqSerialize(&R2_str, &tmp_efq);
// 7. The member computes c = Fp.hash(p || g1 || B || K || B' || K' || T ||
// R1 || R2 || m)
tinysha_init(ctx->hash_alg, &sha_state);
VliSerialize(&p, &(epid20_p.limbs));
tinysha_update(&sha_state, (void const*)&p, sizeof(p));
EFqSerialize(&tmp_str, &epid20_g1);
tinysha_update(&sha_state, (void const*)&tmp_str, sizeof(tmp_str));
EFqSerialize(&tmp_str, &sig->B);
tinysha_update(&sha_state, (void const*)&tmp_str, sizeof(tmp_str));
EFqSerialize(&tmp_str, &sig->K);
tinysha_update(&sha_state, (void const*)&tmp_str, sizeof(tmp_str));
tinysha_update(&sha_state, (void const*)&sigrl_entry->b,
sizeof(sigrl_entry->b));
tinysha_update(&sha_state, (void const*)&sigrl_entry->k,
sizeof(sigrl_entry->k));
tinysha_update(&sha_state, (void const*)&T_str, sizeof(T_str));
tinysha_update(&sha_state, (void const*)&R1_str, sizeof(R1_str));
tinysha_update(&sha_state, (void const*)&R2_str, sizeof(R2_str));
tinysha_update(&sha_state, msg, msg_len);
tinysha_final(digest.digest, &sha_state);
FpFromHash(&c, digest.digest, tinysha_digest_size(&sha_state));
// 8. The member computes smu = (rmu + c * mu) mod p.
FpMul(&smu, &c, &mu);
FpAdd(&smu, &rmu, &smu);
// 9. The member computes snu = (rnu + c * nu) mod p.
FpMul(&snu, &c, &nu);
FpAdd(&snu, &rnu, &snu);
// 10. The member outputs proof = (T, c, smu, snu), a non - revoked proof
FpSerialize(&proof->c, &c);
FpSerialize(&proof->smu, &smu);
FpSerialize(&proof->snu, &snu);
proof->T = T_str;
sts = kEpidNoErr;
} while (0);
FpClear(&mu);
FpClear(&nu);
FpClear(&rmu);
FpClear(&rnu);
return sts;
}