/*############################################################################ # 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 large integer implementation. /*! \file */ #include #include // for CHAR_BIT #include #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/mathtypes.h" #include "epid/member/tiny/math/vli.h" } namespace { //////////////////////////////////////////////////////////////////////// // VliAdd TEST(TinyVliTest, VliAddWorks) { VeryLargeInt result = {0}; VeryLargeInt expected = {0}; VeryLargeInt left = {0}; VeryLargeInt right = {0}; left.word[0] = 1; right.word[0] = 2; expected.word[0] = 3; VliAdd(&result, &left, &right); EXPECT_EQ(expected, result); } TEST(TinyVliTest, VliAddCalculatesCarry) { VeryLargeInt left = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}; VeryLargeInt right = {{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}}; VeryLargeInt expected = {{0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}}; uint32_t expected_carry = 0x1; uint32_t carry = 0; VeryLargeInt result = {0}; carry = VliAdd(&result, &left, &right); EXPECT_EQ(expected, result); EXPECT_EQ(expected_carry, carry); } //////////////////////////////////////////////////////////////////////// // VliMul TEST(TinyVliTest, VliMultWorks) { VeryLargeIntProduct result = {0}; VeryLargeIntProduct expected = {0}; VeryLargeInt left = {0}, right = {0}; left.word[0] = 2; right.word[0] = 2; expected.word[0] = 4; VliMul(&result, &left, &right); EXPECT_EQ(expected, result); } TEST(TinyVliTest, VliMultWorksWithOverflow) { VeryLargeIntProduct result = {0}; VeryLargeIntProduct expected = { {0xfffffffe, 0xfffffffd, 0xfffffffd, 0xfffffffd, 0xfffffffd, 0xfffffffd, 0xfffffffd, 0xfffffffd, 0x1, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2}}; VeryLargeInt left = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}; VeryLargeInt right = {{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2}}; VliMul(&result, &left, &right); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // VliRShift TEST(TinyVliTest, VliRShiftWorks) { VeryLargeInt result = {0}, expected = {0}; VeryLargeInt in = {0}; uint32_t shift = 1; in.word[0] = 4; expected.word[0] = 2; VliRShift(&result, &in, shift); EXPECT_EQ(expected, result); } TEST(TinyVliTest, VliRShiftWorksWithOverlap) { VeryLargeInt result = {0}, expected = {0}; VeryLargeInt in = {0}; uint32_t shift = 4; in.word[0] = 0x00000008; in.word[1] = 0xffffffff; expected.word[0] = 0xf0000000; expected.word[1] = 0x0fffffff; VliRShift(&result, &in, shift); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // VliSub TEST(TinyVliTest, VliSubWorks) { VeryLargeInt result = {0}, expected = {0}; VeryLargeInt left = {0}, right = {0}; uint32_t borrow = 0; uint32_t expected_borrow = 0; left.word[0] = 4; right.word[0] = 2; expected.word[0] = 2; borrow = VliSub(&result, &left, &right); EXPECT_EQ(expected, result); EXPECT_EQ(expected_borrow, borrow); } TEST(TinyVliTest, VliSubWorksWithBorrow) { VeryLargeInt result = {0}; VeryLargeInt expected = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}; VeryLargeInt left = {0}, right = {0}; uint32_t borrow = 0; uint32_t expected_borrow = 1; left.word[0] = 2; right.word[0] = 3; borrow = VliSub(&result, &left, &right); EXPECT_EQ(expected, result); EXPECT_EQ(expected_borrow, borrow); } //////////////////////////////////////////////////////////////////////// // VliSet TEST(TinyVliTest, VliSetWorks) { VeryLargeInt result = {0}; VeryLargeInt in = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}; VliSet(&result, &in); EXPECT_EQ(in, result); } //////////////////////////////////////////////////////////////////////// // VliClear TEST(TinyVliTest, VliClearWorks) { VeryLargeInt expected = {0}; VeryLargeInt in_out = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}; VliClear(&in_out); EXPECT_EQ(expected, in_out); } //////////////////////////////////////////////////////////////////////// // VliIsZero TEST(TinyVliTest, VliIsZeroAcceptsZero) { int is_zero = 0; VeryLargeInt in_zero = {0}; is_zero = VliIsZero(&in_zero); EXPECT_TRUE(is_zero); } TEST(TinyVliTest, VliIsZeroRejectsNonZero) { int is_zero = 0; VeryLargeInt in_nonzero = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}; is_zero = VliIsZero(&in_nonzero); EXPECT_FALSE(is_zero); } //////////////////////////////////////////////////////////////////////// // VliCondSet TEST(TinyVliTest, VliCondSetWorksForTrue) { VeryLargeInt result = {0}; VeryLargeInt true_val = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}; VeryLargeInt false_val = {{0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}}; VliCondSet(&result, &true_val, &false_val, 1); EXPECT_EQ(true_val, result); } TEST(TinyVliTest, VliCondSetWorksForFalse) { VeryLargeInt result = {0}; VeryLargeInt true_val = {{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff}}; VeryLargeInt false_val = {{0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa}}; VliCondSet(&result, &true_val, &false_val, 0); EXPECT_EQ(false_val, result); } //////////////////////////////////////////////////////////////////////// // VliTestBit TEST(TinyVliTest, VliTestBitWorks) { VeryLargeInt in = {0}; uint32_t bit_set = 0; in.word[0] = 4; bit_set = VliTestBit(&in, 1); EXPECT_EQ((uint32_t)0, bit_set); bit_set = VliTestBit(&in, 2); EXPECT_EQ((uint32_t)1, bit_set); } //////////////////////////////////////////////////////////////////////// // VliRand TEST(TinyVliTest, VliRandWorks) { OneTimePad my_prng; VeryLargeInt expected_rand_val1 = {{1, 0, 0, 0, 0, 0, 0, 0}}; my_prng.InitUint8({0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}); VeryLargeInt rand_val1 = {0}; EXPECT_TRUE(VliRand(&rand_val1, &OneTimePad::Generate, &my_prng)); EXPECT_EQ(expected_rand_val1, rand_val1); EXPECT_EQ(256u, my_prng.BitsConsumed()); VeryLargeInt expected_rand_val2 = {{0x1c6f5a0f, 0xeaa878b3, 0xc71dab6b, 0x1a101ad6, 0x1fe6394f, 0x1bec36ab, 0x07a3e97f, 0x36507914}}; VeryLargeInt rand_val2 = {0}; my_prng.InitUint32({0x14795036, 0x7fe9a307, 0xab36ec1b, 0x4f39e61f, 0xd61a101a, 0x6bab1dc7, 0xb378a8ea, 0x0f5a6f1c}); EXPECT_TRUE(VliRand(&rand_val2, &OneTimePad::Generate, &my_prng)); EXPECT_EQ(expected_rand_val2, rand_val2); EXPECT_EQ(256u, my_prng.BitsConsumed()); } //////////////////////////////////////////////////////////////////////// // VliCmp TEST(TinyVliTest, VliCmpWorksForLessThan) { VeryLargeInt in_val1 = {0}; VeryLargeInt in_val2 = {0}; int res = 0; in_val1.word[0] = 1; in_val2.word[0] = 2; res = VliCmp(&in_val1, &in_val2); EXPECT_EQ(-1, res); } TEST(TinyVliTest, VliCmpWorksForEqual) { VeryLargeInt in_val1 = {0}; VeryLargeInt in_val2 = {0}; int res = 0; in_val1.word[0] = 2; in_val2.word[0] = 2; res = VliCmp(&in_val1, &in_val2); EXPECT_EQ(0, res); } TEST(TinyVliTest, VliCmpWorksGreaterThan) { VeryLargeInt in_val1 = {0}; VeryLargeInt in_val2 = {0}; int res = 0; in_val1.word[0] = 1; in_val2.word[0] = 2; res = VliCmp(&in_val2, &in_val1); EXPECT_EQ(1, res); } //////////////////////////////////////////////////////////////////////// // VliModAdd TEST(TinyVliTest, VliModAddWorks) { VeryLargeInt result = {0}; VeryLargeInt left = {0}; VeryLargeInt right = {0}; VeryLargeInt expected = {0}; VeryLargeInt mod = {0xAED33013, 0xD3292DDB, 0x12980A82, 0x0CDC65FB, 0xEE71A49F, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; left.word[0] = 0x9; right.word[0] = 0x8; expected.word[0] = 0x11; VliModAdd(&result, &left, &right, &mod); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // VliModSub TEST(TinyVliTest, VliModSubWorks) { VeryLargeInt result = {0}; VeryLargeInt left = {0}; VeryLargeInt right = {0}; VeryLargeInt expected = {0}; VeryLargeInt mod = {0xAED33013, 0xD3292DDB, 0x12980A82, 0x0CDC65FB, 0xEE71A49F, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; left.word[0] = 0x18; right.word[0] = 0x12; expected.word[0] = 0x6; VliModSub(&result, &left, &right, &mod); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // VliModMul TEST(TinyVliTest, VliModMultWorks) { VeryLargeInt result = {0}; VeryLargeInt left = {0}; VeryLargeInt right = {0}; VeryLargeInt expected = {0}; VeryLargeInt mod = {0xAED33013, 0xD3292DDB, 0x12980A82, 0x0CDC65FB, 0xEE71A49F, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; left.word[0] = 0x10; right.word[0] = 0x2; expected.word[0] = 0x20; VliModMul(&result, &left, &right, &mod); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // VliModExp TEST(TinyVliTest, VliModExpWorks) { VeryLargeInt result = {0}; VeryLargeInt base = {0}; VeryLargeInt exp = {0}; VeryLargeInt mod = {0xAED33013, 0xD3292DDB, 0x12980A82, 0x0CDC65FB, 0xEE71A49F, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; VeryLargeInt expected = {0}; base.word[0] = 0x4; exp.word[0] = 0x2; expected.word[0] = 0x10; VliModExp(&result, &base, &exp, &mod); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // VliModInv TEST(TinyVliTest, VliModInvWorks) { VeryLargeInt a = {0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}; VeryLargeInt q = {0xAED33013, 0xD3292DDB, 0x12980A82, 0x0CDC65FB, 0xEE71A49F, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; VeryLargeInt expected = {0x5a686df6, 0x56b6ab63, 0xdf907c6f, 0x44ad8d51, 0xa5513462, 0xc597ef78, 0x93711b39, 0x15171a1e}; VeryLargeInt result; VliModInv(&result, &a, &q); EXPECT_EQ(result, expected); } //////////////////////////////////////////////////////////////////////// // VliModSquare TEST(TinyVliTest, VliModSquareWorks) { VeryLargeInt result = {0}; VeryLargeInt input = {0}; VeryLargeInt mod = {0xAED33013, 0xD3292DDB, 0x12980A82, 0x0CDC65FB, 0xEE71A49F, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; VeryLargeInt expected = {0}; input.word[0] = 0x4; expected.word[0] = 0x10; VliModSquare(&result, &input, &mod); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // VliModBarrett TEST(TinyVliTest, VliModBarrettWorks) { VeryLargeInt result = {0}; VeryLargeIntProduct product = {0xAED33013, 0xD3292DDB, 0x12980A82, 0x0CDC65FB, 0xEE71A49F, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; VeryLargeInt mod = {0xAED33013, 0xD3292DDB, 0x12980A82, 0x0CDC65FB, 0xEE71A49F, 0x46E5F25E, 0xFFFCF0CD, 0xFFFFFFFF}; VeryLargeInt expected = {0}; product.word[0] += 0xF; expected.word[0] = 0xF; VliModBarrett(&result, &product, &mod); EXPECT_EQ(expected, result); } } // namespace