/*############################################################################ # 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 EFq implementation. /*! \file */ #include <gtest/gtest.h> #include <cstring> #include <random> #include "epid/member/tiny/math/unittests/cmp-testhelper.h" #include "epid/member/tiny/math/unittests/onetimepad.h" extern "C" { #include "epid/member/tiny/math/efq.h" #include "epid/member/tiny/math/fq.h" #include "epid/member/tiny/math/mathtypes.h" #include "epid/member/tiny/math/vli.h" } namespace { //////////////////////////////////////////////////////////////////////// // EFqMulSSCM TEST(TinyEFqTest, EFqMulSSCMWorks) { const EccPointJacobiFq expected = { {0xacd848b1, 0xe3d60553, 0x69271cd1, 0x7cf6090e, 0x16c63bcd, 0xdb0c6cf0, 0x2ab60283, 0x38fc72a8}, {0xf7e0f7d1, 0x6b0cf194, 0x5cf18c77, 0x82a4b960, 0xa6c40a30, 0xf0b3b20f, 0x5f1a477b, 0x7e2a6668}, {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}; const EccPointJacobiFq left = { {0x22cfd6a2, 0x23e82f1e, 0xd50e1450, 0xe853e88c, 0xafa65357, 0x4780716c, 0xffd94b0f, 0x5e643124}, {0x5e9cb480, 0x6d4aaf9c, 0x99f1f606, 0x222d89b0, 0x30b79eab, 0x88844bd6, 0xc65e7c30, 0x4830c4ec}, {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}; const FpElem power = {0x0adf9a12, 0x5cbc9ef4, 0x91762984, 0xa08a22fb, 0x52a6fddf, 0xf51e743e, 0x7b47b24b, 0x389f865f}; EccPointJacobiFq actual = {0}; EFqMulSSCM(&actual, &left, &power); EXPECT_EQ(expected, actual); } TEST(TinyEFqTest, EFqMulSSCMWorksInPlace) { const EccPointJacobiFq expected = { {0xacd848b1, 0xe3d60553, 0x69271cd1, 0x7cf6090e, 0x16c63bcd, 0xdb0c6cf0, 0x2ab60283, 0x38fc72a8}, {0xf7e0f7d1, 0x6b0cf194, 0x5cf18c77, 0x82a4b960, 0xa6c40a30, 0xf0b3b20f, 0x5f1a477b, 0x7e2a6668}, {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}; EccPointJacobiFq left = {{0x22cfd6a2, 0x23e82f1e, 0xd50e1450, 0xe853e88c, 0xafa65357, 0x4780716c, 0xffd94b0f, 0x5e643124}, {0x5e9cb480, 0x6d4aaf9c, 0x99f1f606, 0x222d89b0, 0x30b79eab, 0x88844bd6, 0xc65e7c30, 0x4830c4ec}, {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}; const FpElem power = {0x0adf9a12, 0x5cbc9ef4, 0x91762984, 0xa08a22fb, 0x52a6fddf, 0xf51e743e, 0x7b47b24b, 0x389f865f}; EFqMulSSCM(&left, &left, &power); EXPECT_EQ(expected, left); } //////////////////////////////////////////////////////////////////////// // EFqMultiExp TEST(TinyEFqTest, EFqAffineExpWorks) { EccPointFq efq_left = {0}; EccPointFq efq_right = {{{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}}; EccPointFq efq_expect = {{{0x79171d4b, 0x0f5ac562, 0x3b911d03, 0x0992a2dc, 0x3130dd84, 0x16344c80, 0x436ca13c, 0xaf1d9819}}, {{0x742268cd, 0x070b4ac7, 0x7f2b13b7, 0xe167da7f, 0xd84d16af, 0x9e824ebe, 0x6b5dc0f0, 0x90bd1aa3}}}; FpElem fp_exp = {3}; EFqAffineExp(&efq_left, &efq_right, &fp_exp); EXPECT_EQ(efq_expect, efq_left); } TEST(TinyEFqTest, EFqAffineExpWorksInPlace) { EccPointFq efq_right = {{{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}}; EccPointFq efq_expect = {{{0x79171d4b, 0x0f5ac562, 0x3b911d03, 0x0992a2dc, 0x3130dd84, 0x16344c80, 0x436ca13c, 0xaf1d9819}}, {{0x742268cd, 0x070b4ac7, 0x7f2b13b7, 0xe167da7f, 0xd84d16af, 0x9e824ebe, 0x6b5dc0f0, 0x90bd1aa3}}}; FpElem fp_exp = {3}; EFqAffineExp(&efq_right, &efq_right, &fp_exp); EXPECT_EQ(efq_expect, efq_right); } //////////////////////////////////////////////////////////////////////// // EFqAffineMultiExp TEST(TinyEFqTest, EFqAffineMultiExpWorks) { // eFq2^3*eFq2^3 EccPointFq efq_left = {0}; EccPointFq efq_right = {{{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}}; EccPointFq efq_expect = {{{0x1a178986, 0xeeb06c08, 0x857d79f0, 0x246d0ed6, 0xed31a3b2, 0x7bf832a0, 0x81a8a27b, 0x3d0cab80}}, {{0xfe2a1509, 0x41cda394, 0x42b33efb, 0x2811fa22, 0x0ad56486, 0xe52b1a56, 0xf6dc881c, 0x6fee593f}}}; FpElem fp_exp = {3}; EFqAffineMultiExp(&efq_left, &efq_right, &fp_exp, &efq_right, &fp_exp); EXPECT_EQ(efq_expect, efq_left); } //////////////////////////////////////////////////////////////////////// // EFqMultiExp TEST(TinyEFqTest, EFqMultiExpWorks) { EccPointFq efq_left = {0}; EccPointFq efq_right = {{{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}}; EccPointFq efq_expect = {{{0x1a178986, 0xeeb06c08, 0x857d79f0, 0x246d0ed6, 0xed31a3b2, 0x7bf832a0, 0x81a8a27b, 0x3d0cab80}}, {{0xfe2a1509, 0x41cda394, 0x42b33efb, 0x2811fa22, 0x0ad56486, 0xe52b1a56, 0xf6dc881c, 0x6fee593f}}}; EccPointJacobiFq efqj_left = {0}; EccPointJacobiFq efqj_right; FpElem fp_exp = {3}; EFqFromAffine(&efqj_right, &efq_right); EFqMultiExp(&efqj_left, &efqj_right, &fp_exp, &efqj_right, &fp_exp); EFqToAffine(&efq_left, &efqj_left); EXPECT_EQ(efq_expect, efq_left); } //////////////////////////////////////////////////////////////////////// // EFqAffineAdd TEST(TinyEFqTest, EFqAffineAddWorks) { EccPointFq efq_left = {{{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}}; EccPointFq const efq_expect = { {{0x7305f782, 0x84101559, 0xe065da04, 0xfd373fcf, 0x31d2f725, 0x9b420bdc, 0x622ac9c3, 0xba0ef378}}, {{0x97b2adf0, 0x2935c14b, 0xfc6415b0, 0x48ba036a, 0x61ca7383, 0xcff7f03d, 0x23a2c3e6, 0x0df0d4a5}}}; EFqAffineAdd(&efq_left, &efq_left, &efq_left); EXPECT_EQ(efq_expect, efq_left); } //////////////////////////////////////////////////////////////////////// // EFqAffineDbl TEST(TinyEFqTest, EFqAffineDblWorks) { EccPointFq efq_left = {{{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}}; EccPointFq const efq_expect = { {{0x7305f782, 0x84101559, 0xe065da04, 0xfd373fcf, 0x31d2f725, 0x9b420bdc, 0x622ac9c3, 0xba0ef378}}, {{0x97b2adf0, 0x2935c14b, 0xfc6415b0, 0x48ba036a, 0x61ca7383, 0xcff7f03d, 0x23a2c3e6, 0x0df0d4a5}}}; EFqAffineDbl(&efq_left, &efq_left); EXPECT_EQ(efq_expect, efq_left); } //////////////////////////////////////////////////////////////////////// // EFqDbl TEST(TinyEFqTest, EFqDblWorks) { EccPointJacobiFq efqj_left = { {{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EccPointJacobiFq const efqj_expect = { {{0x7305f782, 0x84101559, 0xe065da04, 0xfd373fcf, 0x31d2f725, 0x9b420bdc, 0x622ac9c3, 0xba0ef378}}, {{0x97b2adf0, 0x2935c14b, 0xfc6415b0, 0x48ba036a, 0x61ca7383, 0xcff7f03d, 0x23a2c3e6, 0x0df0d4a5}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EFqDbl(&efqj_left, &efqj_left); EXPECT_EQ(efqj_expect, efqj_left); } //////////////////////////////////////////////////////////////////////// // EFqAdd TEST(TinyEFqTest, EFqAddWorks) { EccPointJacobiFq efqj_left = { {{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EccPointJacobiFq const efqj_expect = { {{0x7305f782, 0x84101559, 0xe065da04, 0xfd373fcf, 0x31d2f725, 0x9b420bdc, 0x622ac9c3, 0xba0ef378}}, {{0x97b2adf0, 0x2935c14b, 0xfc6415b0, 0x48ba036a, 0x61ca7383, 0xcff7f03d, 0x23a2c3e6, 0x0df0d4a5}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EFqAdd(&efqj_left, &efqj_left, &efqj_left); EXPECT_EQ(efqj_expect, efqj_left); } //////////////////////////////////////////////////////////////////////// // EFqRand // Checks if EFqRand can generate points with Y >= q+1 TEST(TinyEFqTest, EFqRandCanGenerateBigY) { OneTimePad otp({ 0x25, 0xeb, 0x8c, 0x48, 0xff, 0x89, 0xcb, 0x85, 0x4f, 0xc0, 0x90, 0x81, 0xcc, 0x47, 0xed, 0xfc, 0x86, 0x19, 0xb2, 0x14, 0xfe, 0x65, 0x92, 0xd4, 0x8b, 0xfc, 0xea, 0x9c, 0x9d, 0x8e, 0x32, 0x44, 0xd7, 0xd7, 0xe9, 0xf1, 0xf7, 0xde, 0x60, 0x56, 0x8d, 0xe9, 0x89, 0x07, 0x3f, 0x3d, 0x16, 0x39, }); // expected.y >= q+1 EccPointFq expected = {{0xd78542d3, 0xf824c127, 0x81eea621, 0x6990833d, 0x9d843df6, 0x3df36126, 0x435e8eda, 0x2d267586}, {0x1B8DC14B, 0x5967C520, 0x61CECE5D, 0x0290B5BC, 0x49278859, 0x2C523D9A, 0x6D0AE6DE, 0xAE5590C9}}; EccPointFq actual = {0}; EXPECT_TRUE(EFqRand(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(expected, actual); EXPECT_EQ(384u, otp.BitsConsumed()); } // Checks if EFqRand can generate points with Y <= q-1 TEST(TinyEFqTest, EFqRandCanGenerateSmallY) { OneTimePad otp({ 0x47, 0xe7, 0xb0, 0x36, 0x0f, 0x85, 0x91, 0xaa, 0x14, 0x76, 0xb0, 0x16, 0xe5, 0x8d, 0xf1, 0x72, 0x61, 0xb5, 0x54, 0x0a, 0x60, 0xb7, 0x3d, 0x38, 0xd9, 0x95, 0xe7, 0x60, 0xf9, 0xd3, 0x19, 0xf1, 0x8e, 0x8d, 0xd4, 0x74, 0x2b, 0x86, 0xcd, 0xb8, 0xbb, 0x8f, 0x18, 0xfb, 0x89, 0xc2, 0xc7, 0x35, }); // expected.y <= q-1 EccPointFq expected = {{0x5f65199e, 0x59366f56, 0xb1d35d89, 0xf42fdc1f, 0x07fd66d6, 0x95f32cb3, 0xc4ef7101, 0xeb426988}, {0x834171f5, 0xca1c1f05, 0xdcb4d142, 0xbe060756, 0x9185652b, 0xb3b9ede1, 0x671f682e, 0x22d0c94c}}; EccPointFq actual = {0}; EXPECT_TRUE(EFqRand(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(expected, actual); EXPECT_EQ(384u, otp.BitsConsumed()); } TEST(TinyEFqTest, EFqRandWorksForFailedSquareRoot) { // Only last 48 bytes of the given otp will result in x such that // Fq.sqrt of (x^3 + a*x + b) exists. OneTimePad otp({ 0x01, 0x80, 0x3c, 0xd1, 0x08, 0xd8, 0x8d, 0x73, 0xaf, 0xea, 0x79, 0xc8, 0x1e, 0x47, 0x83, 0xc6, 0x95, 0x31, 0x39, 0x03, 0xc4, 0x18, 0xf1, 0x2b, 0x4c, 0x1a, 0x34, 0x50, 0x6d, 0x73, 0x29, 0xd2, 0x0f, 0x40, 0xc4, 0x19, 0x6f, 0xe2, 0xd7, 0x87, 0x1a, 0x99, 0x68, 0x16, 0x09, 0xc3, 0xe7, 0x7e, 0x17, 0x7d, 0x64, 0x9b, 0xa5, 0x39, 0x53, 0xa6, 0x88, 0x20, 0xa2, 0x0a, 0x17, 0x8f, 0xef, 0x57, 0x19, 0xc7, 0xf3, 0x5c, 0x4a, 0xbe, 0x2e, 0xa0, 0xd8, 0x97, 0xb7, 0x41, 0x71, 0x4d, 0x03, 0x80, 0xf8, 0xfd, 0xcd, 0x06, 0x34, 0xd5, 0xc6, 0x02, 0x4c, 0xdb, 0x95, 0xcb, 0x07, 0x4d, 0xc8, 0x4b, 0x4c, 0x2b, 0x14, 0x1e, 0x24, 0x67, 0x07, 0x2d, 0xc4, 0x39, 0xf0, 0xfc, 0xd2, 0x60, 0x0d, 0x0a, 0x17, 0x7c, 0x51, 0x87, 0x79, 0x98, 0xca, 0xdc, 0x94, 0xa0, 0x8c, 0xc1, 0x5e, 0x3c, 0xe9, 0x98, 0x52, 0x73, 0x61, 0x82, 0xec, 0xdc, 0x67, 0x62, 0x0a, 0xb6, 0x60, 0xe9, 0x52, 0xd6, 0xc6, 0xc2, 0x47, 0xe7, 0xb0, 0x36, 0x0f, 0x85, 0x91, 0xaa, 0x14, 0x76, 0xb0, 0x16, 0xe5, 0x8d, 0xf1, 0x72, 0x61, 0xb5, 0x54, 0x0a, 0x60, 0xb7, 0x3d, 0x38, 0xd9, 0x95, 0xe7, 0x60, 0xf9, 0xd3, 0x19, 0xf1, 0x8e, 0x8d, 0xd4, 0x74, 0x2b, 0x86, 0xcd, 0xb8, 0xbb, 0x8f, 0x18, 0xfb, 0x89, 0xc2, 0xc7, 0x35, }); EccPointFq expected = {{0x5f65199e, 0x59366f56, 0xb1d35d89, 0xf42fdc1f, 0x07fd66d6, 0x95f32cb3, 0xc4ef7101, 0xeb426988}, {0x834171f5, 0xca1c1f05, 0xdcb4d142, 0xbe060756, 0x9185652b, 0xb3b9ede1, 0x671f682e, 0x22d0c94c}}; EccPointFq actual = {0}; EXPECT_TRUE(EFqRand(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(expected, actual); EXPECT_EQ(1536u, otp.BitsConsumed()); } //////////////////////////////////////////////////////////////////////// // EFqSet TEST(TinyEFqTest, EFqSetWorks) { EccPointJacobiFq efqj_left = {0}; EccPointJacobiFq const efqj_expect = {{{1}}, {{2}}, {{1}}}; FqElem x = {1}; FqElem y = {2}; EFqSet(&efqj_left, &x, &y); EXPECT_EQ(efqj_expect, efqj_left); } //////////////////////////////////////////////////////////////////////// // EFqIsInf TEST(TinyEFqTest, EFqIsInfPasses) { EccPointJacobiFq const efqj_inf = {{{0}}, {{1}}, {{0}}}; EXPECT_TRUE(EFqIsInf(&efqj_inf)); } TEST(TinyEFqTest, EFqIsInfFails) { EccPointJacobiFq const efqj_noninf = {{{1}}, {{2}}, {{1}}}; EXPECT_FALSE(EFqIsInf(&efqj_noninf)); } //////////////////////////////////////////////////////////////////////// // EFqFromAffine TEST(TinyEFqTest, FqFromAffineWorks) { EccPointJacobiFq efqj_left = {0}; EccPointJacobiFq const efqj_expect = {{{1}}, {{2}}, {{1}}}; EccPointFq efq_left = {{{1}}, {{2}}}; EFqFromAffine(&efqj_left, &efq_left); EXPECT_EQ(efqj_expect, efqj_left); } //////////////////////////////////////////////////////////////////////// // EFqToAffine TEST(TinyEFqTest, EFqToAffineWorks) { EccPointFq efq_left = {0}; EccPointFq const efq_expect = {{{1}}, {{2}}}; EccPointJacobiFq efqj_left = {{{1}}, {{2}}, {{1}}}; EFqToAffine(&efq_left, &efqj_left); EXPECT_EQ(efq_expect, efq_left); } //////////////////////////////////////////////////////////////////////// // EFqNeg TEST(TinyEFqTest, EFqNegWorks) { EccPointJacobiFq efqj_left = {0}; EccPointJacobiFq efqj_right = { {{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EccPointJacobiFq const efqj_expect = { {{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x8f98a4d1, 0x0a561b5c, 0xa50112b5, 0x226c8304, 0xe3b0f033, 0xf16b932e, 0x50f59e7c, 0x879ad734}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EFqNeg(&efqj_left, &efqj_right); EXPECT_EQ(efqj_expect, efqj_left); } //////////////////////////////////////////////////////////////////////// // EFqEq TEST(TinyEFqTest, EFqEqPasses) { EccPointJacobiFq const efqj_left = {{{1}}, {{2}}, {{1}}}; EccPointJacobiFq const efqj_right = {{{1}}, {{2}}, {{1}}}; EXPECT_TRUE(EFqEq(&efqj_left, &efqj_right)); } TEST(TinyEFqTest, EFqEqFails) { EccPointJacobiFq const efqj_left = {{{1}}, {{2}}, {{1}}}; EccPointJacobiFq const efqj_right = { {{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EXPECT_FALSE(EFqEq(&efqj_left, &efqj_right)); } //////////////////////////////////////////////////////////////////////// // EFqHash TEST(TinyEFqTest, EFqHashWithSha512Works) { EccPointFq efq_result = {0}; EccPointFq efq_expect = {{{0x992a96e4, 0x42f7b394, 0xf3bada9c, 0xb4033d83, 0x21979b9b, 0xbc82a6a2, 0x55555586, 0x8c62a02d}}, {{0x406c8f03, 0xe691d8f3, 0xadf2f27b, 0x69540cc6, 0xe02b87f7, 0x217d5424, 0x17b9fbe5, 0x4c0ea762}}}; unsigned char const msg_buf[] = {'a', 'b', 'c'}; size_t len = sizeof(msg_buf); HashAlg hashalg = kSha512; EXPECT_TRUE(EFqHash(&efq_result, msg_buf, len, hashalg)); EXPECT_EQ(efq_expect, efq_result); } TEST(TinyEFqTest, EFqHashWithSha256Works) { EccPointFq efq_result = {0}; EccPointFq efq_expect = {{{0x8008953d, 0xd54a103c, 0x70e6186b, 0x54f5a62a, 0xadbe836e, 0xf3716581, 0x88ff2562, 0x2ebb504d}}, {{0xdc48f9f7, 0x48aa0d6c, 0x623e2c1f, 0x7ecdf02e, 0x07f07a32, 0xbd6738b1, 0xb13f3cb4, 0x8a43a104}}}; unsigned char const msg_buf[] = {'a', 'b', 'c'}; size_t len = sizeof(msg_buf); HashAlg hashalg = kSha256; EXPECT_TRUE(EFqHash(&efq_result, msg_buf, len, hashalg)); EXPECT_EQ(efq_expect, efq_result); } TEST(TinyEFqTest, HashWorksForResultYSmallerThanHalfOfQAndEven) { std::vector<uint8_t> msg = {'a', 'a', 'd'}; EccPointFq result; EccPointFq expected = {{0xb315d67e, 0x1924ae56, 0xcf527861, 0xebb789b6, 0x3f429d2a, 0xb193bf9a, 0x6bd8502f, 0x5e73be39}, {0x0bd51968, 0x0f13472d, 0xc96b5096, 0xa9cd4491, 0x4ab668cf, 0x2123d56c, 0xf30af180, 0x0db43c33}}; EXPECT_TRUE(EFqHash(&result, msg.data(), msg.size(), kSha512)); EXPECT_EQ(expected, result); } TEST(TinyEFqTest, HashWorksForResultYSmallerThanHalfOfQAndOdd) { std::vector<uint8_t> msg = {'a', 'a', 'c'}; EccPointFq result; EccPointFq expected = {{0x81D359E2, 0xF438B2AC, 0xAA4342EB, 0x80042B18, 0x850E1C62, 0x90860717, 0xC79A1AB8, 0xF8F4F2F6}, {0xC1A2BA30, 0x369C0D70, 0x03EAF9DD, 0x4F93FC67, 0xBB6E5D10, 0x441B22F9, 0xEC70C946, 0xE8D39BD4}}; EXPECT_TRUE(EFqHash(&result, msg.data(), msg.size(), kSha512)); EXPECT_EQ(expected, result); } TEST(TinyEFqTest, HashWorksForResultYLargerThanHalfOfQAndOdd) { std::vector<uint8_t> msg = {'a', 'a', 'b'}; EccPointFq result; EccPointFq expected = {{0x31F874DA, 0x62DB014E, 0x4A4FC69A, 0xC1DCC122, 0xC423DAF8, 0x27AB3AAC, 0xF1DE0993, 0x07906282}, {0x8DA507A4, 0x568E1D1E, 0x6D373E90, 0x99A18DA4, 0xC5717AA2, 0x98C222F5, 0x0A2ADDF2, 0xA1212A44}}; EFqHash(&result, msg.data(), msg.size(), kSha512); EXPECT_EQ(expected, result); } TEST(TinyEFqTest, HashWorksForResultYLargerThanHalfOfQAndEven) { std::vector<uint8_t> msg = {'a', 'a', 'e'}; EccPointFq result; EccPointFq expected = {{0xA798F97C, 0xF24EC264, 0xD4C051F4, 0xBA4A5B45, 0xD2CF5996, 0x121A3F66, 0x222279F0, 0x208E4FD4}, {0x3C816617, 0x6CF621EB, 0x8B8DAFC4, 0x63EB39C7, 0xE6C8AF5C, 0x32C732D0, 0xC5C46152, 0x114E8AE0}}; EFqHash(&result, msg.data(), msg.size(), kSha512); EXPECT_EQ(expected, result); } //////////////////////////////////////////////////////////////////////// // EFqCp TEST(TinyEFqTest, EFqCpWorks) { const EccPointFq ecfq_point = { {{0x76ABB18A, 0x92C0F7B9, 0x2C1A37E0, 0x7FDF6CA1, 0xE3401760, 0x66EB7D52, 0x918D50A7, 0x12A65BD6}}, {{0x1F3A8B42, 0xC8D3127F, 0x6D96F7CD, 0xEA6FE2F6, 0x0AC0B46B, 0x557A5F30, 0xAF075250, 0x786528CB}}}; EccPointFq result_ecfq_point = {0}; EFqCp(&result_ecfq_point, &ecfq_point); EXPECT_EQ(ecfq_point, result_ecfq_point); } //////////////////////////////////////////////////////////////////////// // EFqEqAffine TEST(TinyEFqTest, EFqEqAffinePasses) { EccPointFq efq_left = {{{1}}, {{2}}}; EccPointFq efq_right = {{{1}}, {{2}}}; EXPECT_TRUE(EFqEqAffine(&efq_left, &efq_right)); } TEST(TinyEFqTest, EFqEqAffineFails) { EccPointFq efq_left = {{{1}}, {{2}}}; EccPointFq efq_right = {{{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x8f98a4d1, 0x0a561b5c, 0xa50112b5, 0x226c8304, 0xe3b0f033, 0xf16b932e, 0x50f59e7c, 0x879ad734}}}; EXPECT_FALSE(EFqEqAffine(&efq_left, &efq_right)); } //////////////////////////////////////////////////////////////////////// // EFqCondSet TEST(TinyEFqTest, EFqCondSetWorksForTrue) { #define TRUE 1 EccPointJacobiFq efqj_left = {0}; EccPointJacobiFq efqj_right = { {{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EccPointJacobiFq efqj_expect = {{{1}}, {{2}}, {{1}}}; EFqCondSet(&efqj_left, &efqj_expect, &efqj_right, TRUE); EXPECT_EQ(efqj_left, efqj_expect); } TEST(TinyEFqTest, EFqCondSetWorksForFalse) { #define FALSE 0 EccPointJacobiFq efqj_left = {0}; EccPointJacobiFq efqj_right = {{{1}}, {{2}}, {{1}}}; EccPointJacobiFq efqj_expect = { {{0x76abb18a, 0x92c0f7b9, 0x2c1a37e0, 0x7fdf6ca1, 0xe3401760, 0x66eb7d52, 0x918d50a7, 0x12a65bd6}}, {{0x1f3a8b42, 0xc8d3127f, 0x6d96f7cd, 0xea6fe2f6, 0x0ac0b46b, 0x557a5f30, 0xaf075250, 0x786528cb}}, {{0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}}; EFqCondSet(&efqj_left, &efqj_right, &efqj_expect, FALSE); EXPECT_EQ(efqj_left, efqj_expect); } //////////////////////////////////////////////////////////////////////// // EFqJCp TEST(TinyEFqTest, EFqJCpWorks) { const EccPointJacobiFq efqj = {{{1}}, {{2}}, {{1}}}; EccPointJacobiFq efqj_result = {0}; EFqJCp(&efqj_result, &efqj); EXPECT_EQ(efqj, efqj_result); } //////////////////////////////////////////////////////////////////////// // EFqInf TEST(TinyEFqTest, EFqInfWorks) { EccPointJacobiFq efqj_left; EccPointJacobiFq efqj_expect = {{{0}}, {{1}}, {{0}}}; EFqInf(&efqj_left); EXPECT_EQ(efqj_expect, efqj_left); } //////////////////////////////////////////////////////////////////////// // EFqOnCurve TEST(TinyEFqTest, EFqOnCurvePasses) { const EccPointFq ecfq_point = { {{0x76ABB18A, 0x92C0F7B9, 0x2C1A37E0, 0x7FDF6CA1, 0xE3401760, 0x66EB7D52, 0x918D50A7, 0x12A65BD6}}, {{0x1F3A8B42, 0xC8D3127F, 0x6D96F7CD, 0xEA6FE2F6, 0x0AC0B46B, 0x557A5F30, 0xAF075250, 0x786528CB}}}; EXPECT_EQ(1, EFqOnCurve(&ecfq_point)); } TEST(TinyEFqTest, EFqOnCurveFails) { EccPointFq bad_ecfq_point = { {{0x76ABB18A, 0x92C0F7B9, 0x2C1A37E0, 0x7FDF6CA1, 0xE3401760, 0x66EB7D52, 0x918D50A7, 0x12A65BD6}}, {{0x1F3A8B42, 0xC8D3127F, 0x6D96F7CD, 0xEA6FE2F6, 0x0AC0B46B, 0x557A5F30, 0xAF075250, 0x786528CB}}}; uint8_t* ecpq_vec = (uint8_t*)bad_ecfq_point.x.limbs.word; ecpq_vec[31]++; EXPECT_EQ(0, EFqOnCurve(&bad_ecfq_point)); } //////////////////////////////////////////////////////////////////////// // EFqJOnCurve TEST(TinyEFqTest, EFqJOnCurvePasses) { EccPointJacobiFq efqj = {{{1}}, {{2}}, {{1}}}; EXPECT_TRUE(EFqJOnCurve(&efqj)); } TEST(TinyEFqTest, EFqJOnCurveFails) { EccPointJacobiFq efqj = {{{1}}, {{4}}, {{1}}}; EXPECT_FALSE(EFqJOnCurve(&efqj)); } TEST(TinyEFqTest, EFqJOnCurveAcceptsPointAtInfinity) { EccPointJacobiFq infinity = {{{0}}, {{1}}, {{0}}}; EXPECT_TRUE(EFqJOnCurve(&infinity)); } //////////////////////////////////////////////////////////////////////// // EFqJRand // Checks if EFqJRand can generate points with Y >= q+1 TEST(TinyEFqTest, EFqJRandCanGenerateBigY) { OneTimePad otp({ 0x25, 0xeb, 0x8c, 0x48, 0xff, 0x89, 0xcb, 0x85, 0x4f, 0xc0, 0x90, 0x81, 0xcc, 0x47, 0xed, 0xfc, 0x86, 0x19, 0xb2, 0x14, 0xfe, 0x65, 0x92, 0xd4, 0x8b, 0xfc, 0xea, 0x9c, 0x9d, 0x8e, 0x32, 0x44, 0xd7, 0xd7, 0xe9, 0xf1, 0xf7, 0xde, 0x60, 0x56, 0x8d, 0xe9, 0x89, 0x07, 0x3f, 0x3d, 0x16, 0x39, }); // expected.y >= q+1 EccPointJacobiFq expected = { {0xd78542d3, 0xf824c127, 0x81eea621, 0x6990833d, 0x9d843df6, 0x3df36126, 0x435e8eda, 0x2d267586}, {0x1B8DC14B, 0x5967C520, 0x61CECE5D, 0x0290B5BC, 0x49278859, 0x2C523D9A, 0x6D0AE6DE, 0xAE5590C9}, {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}; EccPointJacobiFq actual = {0}; EXPECT_TRUE(EFqJRand(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(expected, actual); EXPECT_EQ(384u, otp.BitsConsumed()); } // Checks if EFqJRand can generate points with Y <= q-1 TEST(TinyEFqTest, EFqJRandCanGenerateSmallY) { OneTimePad otp({ 0x47, 0xe7, 0xb0, 0x36, 0x0f, 0x85, 0x91, 0xaa, 0x14, 0x76, 0xb0, 0x16, 0xe5, 0x8d, 0xf1, 0x72, 0x61, 0xb5, 0x54, 0x0a, 0x60, 0xb7, 0x3d, 0x38, 0xd9, 0x95, 0xe7, 0x60, 0xf9, 0xd3, 0x19, 0xf1, 0x8e, 0x8d, 0xd4, 0x74, 0x2b, 0x86, 0xcd, 0xb8, 0xbb, 0x8f, 0x18, 0xfb, 0x89, 0xc2, 0xc7, 0x35, }); // expected.y <= q-1 EccPointJacobiFq expected = { {0x5f65199e, 0x59366f56, 0xb1d35d89, 0xf42fdc1f, 0x07fd66d6, 0x95f32cb3, 0xc4ef7101, 0xeb426988}, {0x834171f5, 0xca1c1f05, 0xdcb4d142, 0xbe060756, 0x9185652b, 0xb3b9ede1, 0x671f682e, 0x22d0c94c}, {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}; EccPointJacobiFq actual = {0}; EXPECT_TRUE(EFqJRand(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(expected, actual); EXPECT_EQ(384u, otp.BitsConsumed()); } TEST(TinyEFqTest, EFqJRandWorksForFailedSquareRoot) { // Only last 48 bytes of the given otp will result in x such that // Fq.sqrt of (x^3 + a*x + b) exists. OneTimePad otp({ 0x01, 0x80, 0x3c, 0xd1, 0x08, 0xd8, 0x8d, 0x73, 0xaf, 0xea, 0x79, 0xc8, 0x1e, 0x47, 0x83, 0xc6, 0x95, 0x31, 0x39, 0x03, 0xc4, 0x18, 0xf1, 0x2b, 0x4c, 0x1a, 0x34, 0x50, 0x6d, 0x73, 0x29, 0xd2, 0x0f, 0x40, 0xc4, 0x19, 0x6f, 0xe2, 0xd7, 0x87, 0x1a, 0x99, 0x68, 0x16, 0x09, 0xc3, 0xe7, 0x7e, 0x17, 0x7d, 0x64, 0x9b, 0xa5, 0x39, 0x53, 0xa6, 0x88, 0x20, 0xa2, 0x0a, 0x17, 0x8f, 0xef, 0x57, 0x19, 0xc7, 0xf3, 0x5c, 0x4a, 0xbe, 0x2e, 0xa0, 0xd8, 0x97, 0xb7, 0x41, 0x71, 0x4d, 0x03, 0x80, 0xf8, 0xfd, 0xcd, 0x06, 0x34, 0xd5, 0xc6, 0x02, 0x4c, 0xdb, 0x95, 0xcb, 0x07, 0x4d, 0xc8, 0x4b, 0x4c, 0x2b, 0x14, 0x1e, 0x24, 0x67, 0x07, 0x2d, 0xc4, 0x39, 0xf0, 0xfc, 0xd2, 0x60, 0x0d, 0x0a, 0x17, 0x7c, 0x51, 0x87, 0x79, 0x98, 0xca, 0xdc, 0x94, 0xa0, 0x8c, 0xc1, 0x5e, 0x3c, 0xe9, 0x98, 0x52, 0x73, 0x61, 0x82, 0xec, 0xdc, 0x67, 0x62, 0x0a, 0xb6, 0x60, 0xe9, 0x52, 0xd6, 0xc6, 0xc2, 0x47, 0xe7, 0xb0, 0x36, 0x0f, 0x85, 0x91, 0xaa, 0x14, 0x76, 0xb0, 0x16, 0xe5, 0x8d, 0xf1, 0x72, 0x61, 0xb5, 0x54, 0x0a, 0x60, 0xb7, 0x3d, 0x38, 0xd9, 0x95, 0xe7, 0x60, 0xf9, 0xd3, 0x19, 0xf1, 0x8e, 0x8d, 0xd4, 0x74, 0x2b, 0x86, 0xcd, 0xb8, 0xbb, 0x8f, 0x18, 0xfb, 0x89, 0xc2, 0xc7, 0x35, }); EccPointJacobiFq expected = { {0x5f65199e, 0x59366f56, 0xb1d35d89, 0xf42fdc1f, 0x07fd66d6, 0x95f32cb3, 0xc4ef7101, 0xeb426988}, {0x834171f5, 0xca1c1f05, 0xdcb4d142, 0xbe060756, 0x9185652b, 0xb3b9ede1, 0x671f682e, 0x22d0c94c}, {0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}}; EccPointJacobiFq actual = {0}; EXPECT_TRUE(EFqJRand(&actual, OneTimePad::Generate, &otp)); EXPECT_EQ(expected, actual); EXPECT_EQ(1536u, otp.BitsConsumed()); } } // namespace