/*############################################################################ # 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. ############################################################################*/ /// Unit tests of Fp implementation. /*! \file */ #include #include "epid/member/tiny/math/unittests/cmp-testhelper.h" #include "epid/member/tiny/math/unittests/onetimepad.h" extern "C" { #include "epid/member/tiny/math/fp.h" #include "epid/member/tiny/math/mathtypes.h" } namespace { //////////////////////////////////////////////////////////////////////// // FpInField TEST(TinyFpTest, FpInFieldPasses) { FpElem zero = {0}; FpElem p_minus_one = {{0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; EXPECT_TRUE(FpInField(&zero)); EXPECT_TRUE(FpInField(&p_minus_one)); } TEST(TinyFpTest, FpInFieldFails) { FpElem p = {{0xD10B500D, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; EXPECT_FALSE(FpInField(&p)); } //////////////////////////////////////////////////////////////////////// // FpAdd TEST(TinyFpTest, FpAddWorks) { FpElem result = {0}, expected = {0}, left = {0}, right = {0}; left.limbs.word[5] = 1; right.limbs.word[5] = 2; expected.limbs.word[5] = 3; FpAdd(&result, &left, &right); EXPECT_EQ(expected, result); FpElem p_minus_one = {0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; right = {2, 0, 0, 0, 0, 0, 0, 0}; expected = {1, 0, 0, 0, 0, 0, 0, 0}; FpAdd(&result, &p_minus_one, &right); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // FpMul TEST(TinyFpTest, FpMultWorks) { FpElem left = {0x22cfd6a2, 0x23e82f1e, 0xd50e1450, 0xe853e88c, 0xafa65357, 0x4780716c, 0xffd94b0f, 0x5e643124}; FpElem right = {0x848cdb73, 0x6399829e, 0xcaa20cc0, 0x1b02bff6, 0x2b477bd2, 0xf9d48534, 0xff7929a0, 0xd4745161}; FpElem expected = {0x3f172ebf, 0xf2219fce, 0x73591802, 0x7a7dbc7f, 0xf82ed0df, 0xb8c0c56d, 0x3395ff68, 0x83d64983}; FpElem result = {0}; FpMul(&result, &left, &right); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // FpSub TEST(TinyFpTest, FpSubWorks) { FpElem result = {0}, expected = {0}, left = {0}, right = {0}; left.limbs.word[4] = 2; right.limbs.word[4] = 1; expected.limbs.word[4] = 1; FpSub(&result, &left, &right); EXPECT_EQ(expected, result); left = {1, 0, 0, 0, 0, 0, 0, 0}; right = {2, 0, 0, 0, 0, 0, 0, 0}; FpElem p_minus_one = {0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; FpSub(&result, &left, &right); EXPECT_EQ(p_minus_one, result); } //////////////////////////////////////////////////////////////////////// // FpExp TEST(TinyFpTest, FpExpWorks) { FpElem result = {0}, expected = {0}, in = {0}; VeryLargeInt exp = {0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; in.limbs.word[0] = 1; expected.limbs.word[0] = 1; FpExp(&result, &in, &exp); EXPECT_EQ(expected, result); exp = {4, 0, 0, 0, 0, 0, 0, 0}; in = {{0x0000007B, 0, 0, 0, 0, 0, 0, 0}}; expected = {{0x0DA48871, 0, 0, 0, 0, 0, 0, 0}}; FpExp(&result, &in, &exp); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // FpNeg TEST(TinyFpTest, FpNegWorks) { FpElem const pairing_p = {{0xD10B500D, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; FpElem neg_value = {0}; FpElem one = {{1, 0, 0, 0, 0, 0, 0, 0}}; FpElem minus_one = pairing_p; --minus_one.limbs.word[0]; FpNeg(&neg_value, &one); EXPECT_EQ(minus_one, neg_value); FpElem value = {{0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; FpNeg(&neg_value, &value); FpNeg(&neg_value, &neg_value); EXPECT_EQ(value, neg_value); } //////////////////////////////////////////////////////////////////////// // FpEq TEST(TinyFpTest, FpEqPasses) { FpElem a = {{0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; FpElem c = {{0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; EXPECT_TRUE(FpEq(&a, &c)); } TEST(TinyFpTest, FpEqFails) { FpElem a = {{0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; FpElem b = {{0, 0, 0, 0, 0, 0, 1, 0}}; EXPECT_FALSE(FpEq(&a, &b)); } //////////////////////////////////////////////////////////////////////// // FpInv TEST(TinyFpTest, FpInvWorks) { FpElem a = {{0x22cfd6a2, 0x23e82f1e, 0xd50e1450, 0xe853e88c, 0xafa65357, 0x4780716c, 0xffd94b0f, 0x5e643124}}; FpElem expected = {{0xd97deaf7, 0xa6011d83, 0x3c381713, 0x92472e34, 0x997861e8, 0xc1dfdc87, 0x157eb11b, 0xc9cd1238}}; FpElem result; FpInv(&result, &a); EXPECT_EQ(result, expected); } //////////////////////////////////////////////////////////////////////// // FpRand TEST(TinyFpTest, FpRandConsumes384BitsOfEntropy) { OneTimePad otp(64); FpElem actual = {0}; EXPECT_TRUE(FpRand(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(384u, otp.BitsConsumed()); } TEST(TinyFpTest, FpRandWorks) { OneTimePad otp({// slen bits 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // p + 1 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A, 0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0E}); FpElem expected = {{1, 0, 0, 0, 0, 0, 0, 0}}; FpElem actual = {0}; EXPECT_TRUE(FpRand(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(expected, actual); } //////////////////////////////////////////////////////////////////////// // FpRandNonzero TEST(TinyFpTest, FpRandNonzeroConsumes384BitsOfEntropy) { OneTimePad otp(64); FpElem actual = {0}; EXPECT_TRUE(FpRandNonzero(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(384u, otp.BitsConsumed()); } TEST(TinyFpTest, FpRandNonzeroWorks) { OneTimePad otp({// slen bits 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // p - 1 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A, 0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0C}); FpElem expected = {{1, 0, 0, 0, 0, 0, 0, 0}}; FpElem actual = {0}; EXPECT_TRUE(FpRandNonzero(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(expected, actual); } //////////////////////////////////////////////////////////////////////// // FpClear TEST(TinyFpTest, FpClearWorks) { FpElem zero = {0}; FpElem a = {{0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; FpClear(&a); EXPECT_EQ(zero, a); } //////////////////////////////////////////////////////////////////////// // FpSet TEST(TinyFpTest, FpSetWorks) { uint32_t small = 0xffffffff; FpElem expected = {{small, 0, 0, 0, 0, 0, 0, 0}}; FpElem result = {{0xD10B500C, 0xF62D536C, 0x1299921A, 0x0CDC65FB, 0xEE71A49E, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}}; FpSet(&result, small); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // FpFromHash TEST(TinyFpTest, FpFromHashWorks) { FpElem p_mod_p; FpElem zero = {0}; uint8_t p_str[32] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xCD, 0x46, 0xE5, 0xF2, 0x5E, 0xEE, 0x71, 0xA4, 0x9E, 0x0C, 0xDC, 0x65, 0xFB, 0x12, 0x99, 0x92, 0x1A, 0xF6, 0x2D, 0x53, 0x6C, 0xD1, 0x0B, 0x50, 0x0D}; FpFromHash(&p_mod_p, p_str, sizeof(p_str)); EXPECT_EQ(zero, p_mod_p); FpElem one = {{1, 0, 0, 0, 0, 0, 0, 0}}; uint8_t one_str[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; FpElem one_mod_p; FpFromHash(&one_mod_p, one_str, sizeof(one_str)); EXPECT_EQ(one, one_mod_p); } } // namespace