blob: 9fc003693d34c482e0900fe3eb63bc79b112d602 [file]
// Copyright 2026 The BoringSSL Authors
//
// 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
//
// https://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.
#include <limits.h>
#include <stdint.h>
#include <algorithm>
#include <vector>
#include <gtest/gtest.h>
#include "../test/test_util.h"
#include "internal.h"
using namespace bssl;
namespace {
#if !defined(BORINGSSL_SHARED_LIBRARY)
TEST(Curve25519Test, MapToCurveElligator2RFC9380) {
struct Elligator2Test {
// RFC 9380 big-endian hex strings
const char *u_hex;
const char *qx_hex;
const char *qy_hex;
};
const Elligator2Test kTests[] = {
// RFC 9380, Appendix J.4.1 (curve25519_XMD:SHA-512_ELL2_RO_)
// We include this because we are testing map_to_curve_elligator2
{"005fe8a7b8fef0a16c105e6cadf5a6740b3365e18692a9c05bfbb4"
"d97f645a6a",
"36b4df0c864c64707cbf6cf36e9ee2c09a6cb93b28313c169be295"
"61bb904f98",
"6cd59d664fb58c66c892883cd0eb792e52055284dac3907dd756b4"
"5d15c3983d"},
{"1347edbec6a2b5d8c02e058819819bee177077c9d10a4ce165aab0"
"fd0252261a",
"3fa114783a505c0b2b2fbeef0102853c0b494e7757f2a089d0daae"
"7ed9a0db2b",
"76c0fe7fec932aaafb8eefb42d9cbb32eb931158f469ff3050af15"
"cfdbbeff94"},
{"49bed021c7a3748f09fa8cdfcac044089f7829d3531066ac9e74e0"
"994e05bc7d",
"16b3d86e056b7970fa00165f6f48d90b619ad618791661b7b5e1ec"
"78be10eac1",
"4ab256422d84c5120b278cbdfc4e1facc5baadffeccecf8ee9bf39"
"46106d50ca"},
{"5c36525b663e63389d886105cee7ed712325d5a97e60e140aba7e2"
"ce5ae851b6",
"7ec29ddbf34539c40adfa98fcb39ec36368f47f30e8f888cc7e86f"
"4d46e0c264",
"10d1abc1cae2d34c06e247f2141ba897657fb39f1080d54f09ce0a"
"f128067c74"},
{"6412b7485ba26d3d1b6c290a8e1435b2959f03721874939b21782d"
"f17323d160",
"71de3dadfe268872326c35ac512164850860567aea0e7325e6b91a"
"98f86533ad",
"26a08b6e9a18084c56f2147bf515414b9b63f1522e1b6c5649f7d4"
"b0324296ec"},
{"24c7b46c1c6d9a21d32f5707be1380ab82db1054fde82865d5c9e3"
"d968f287b2",
"5704069021f61e41779e2ba6b932268316d6d2a6f064f997a22fef"
"16d1eaeaca",
"50483c7540f64fb4497619c050f2c7fe55454ec0f0e79870bb4430"
"2e34232210"},
{"5e123990f11bbb5586613ffabdb58d47f64bb5f2fa115f8ea8df01"
"88e0c9e1b5",
"7a94d45a198fb5daa381f45f2619ab279744efdd8bd8ed587fc5b6"
"5d6cea1df0",
"67d44f85d376e64bb7d713585230cdbfafc8e2676f7568e0b6ee59"
"361116a6e1"},
{"5e8553eb00438a0bb1e7faa59dec6d8087f9c8011e5fb8ed9df31c"
"b6c0d4ac19",
"30506fb7a32136694abd61b6113770270debe593027a968a01f271"
"e146e60c18",
"7eeee0e706b40c6b5174e551426a67f975ad5a977ee2f01e8e20a6"
"d612458c3b"},
{"20f481e85da7a3bf60ac0fb11ed1d0558fc6f941b3ac5469aa8b56"
"ec883d6d7d",
"02d606e2699b918ee36f2818f2bc5013e437e673c9f9b9cdc15fd0"
"c5ee913970",
"29e9dc92297231ef211245db9e31767996c5625dfbf92e1c8107ef"
"887365de1e"},
{"017d57fd257e9a78913999a23b52ca988157a81b09c5442501d07f"
"ed20869465",
"38920e9b988d1ab7449c0fa9a6058192c0c797bb3d42ac34572434"
"1a1aa98745",
"24dcc1be7c4d591d307e89049fd2ed30aae8911245a9d8554bf603"
"2e5aa40d3d"},
// RFC 9380, Appendix J.4.2 (curve25519_XMD:SHA-512_ELL2_NU_)
{"608d892b641f0328523802a6603427c26e55e6f27e71a91a478148"
"d45b5093cd",
"51125222da5e763d97f3c10fcc92ea6860b9ccbbd2eb1285728f56"
"6721c1e65b",
"343d2204f812d3dfc5304a5808c6c0d81a903a5d228b342442aa3c"
"9ba5520a3d"},
{"46f5b22494bfeaa7f232cc8d054be68561af50230234d7d1d63d1d"
"9abeca8da5",
"7d56d1e08cb0ccb92baf069c18c49bb5a0dcd927eff8dcf75ca921"
"ef7f3e6eeb",
"404d9a7dc25c9c05c44ab9a94590e7c3fe2dcec74533a0b24b188a"
"5d5dacf429"},
{"235fe40c443766ce7e18111c33862d66c3b33267efa50d50f9e8e5"
"d252a40aaa",
"3fbe66b9c9883d79e8407150e7c2a1c8680bee496c62fabe4619a7"
"2b3cabe90f",
"08ec476147c9a0a3ff312d303dbbd076abb7551e5fce82b48ab14b"
"433f8d0a7b"},
{"001e92a544463bda9bd04ddbe3d6eed248f82de32f522669efc5dd"
"ce95f46f5b",
"227e0bb89de700385d19ec40e857db6e6a3e634b1c32962f370d26"
"f84ff19683",
"5f86ff3851d262727326a32c1bf7655a03665830fa7f1b8b1e5a09"
"d85bc66e4a"},
{"1a68a1af9f663592291af987203393f707305c7bac9c8d63d6a729"
"bdc553dc19",
"3bcd651ee54d5f7b6013898aab251ee8ecc0688166fce6e9548d38"
"472f6bd196",
"1bb36ad9197299f111b4ef21271c41f4b7ecf5543db8bb5931307e"
"bdb2eaa465"},
};
for (const auto &t : kTests) {
std::vector<uint8_t> u_bytes, expected_qx, expected_qy;
ASSERT_TRUE(DecodeHex(&u_bytes, t.u_hex));
ASSERT_TRUE(DecodeHex(&expected_qx, t.qx_hex));
ASSERT_TRUE(DecodeHex(&expected_qy, t.qy_hex));
ASSERT_EQ(u_bytes.size(), 32u);
ASSERT_EQ(expected_qx.size(), 32u);
ASSERT_EQ(expected_qy.size(), 32u);
// RFC 9380 test vectors encode coordinates in big-endian hex, while
// Curve25519 serializes field elements in little-endian.
std::reverse(u_bytes.begin(), u_bytes.end());
std::reverse(expected_qx.begin(), expected_qx.end());
std::reverse(expected_qy.begin(), expected_qy.end());
uint8_t qx[32], qy[32];
map_to_curve_curve25519_elligator2(qx, qy, u_bytes.data());
EXPECT_EQ(Bytes(qx), Bytes(expected_qx));
EXPECT_EQ(Bytes(qy), Bytes(expected_qy));
}
}
TEST(Curve25519Test, CPaceX25519GeneratorTest) {
// Test vector from draft-irtf-cfrg-cpace-21, Appendix B.1.1
const uint8_t u_bytes[32] = {0x03, 0x99, 0x80, 0x87, 0xbd, 0xb1, 0xa2, 0x61,
0x7b, 0xbe, 0x25, 0xef, 0x5a, 0x7c, 0x18, 0xcd,
0x4f, 0x84, 0xf9, 0x02, 0x32, 0x87, 0x01, 0x79,
0x09, 0x58, 0x75, 0x5e, 0xe4, 0xae, 0xd1, 0x53};
const uint8_t expected_g[32] = {
0xd0, 0x4b, 0xf6, 0xd4, 0x1f, 0x6a, 0x28, 0x96, 0x32, 0xa2, 0xe9,
0x29, 0xfa, 0x29, 0xbe, 0xbd, 0x51, 0x09, 0x25, 0x12, 0xa7, 0x82,
0x9f, 0xdd, 0xe7, 0xd3, 0x14, 0xb6, 0x2f, 0x05, 0xa7, 0x3f};
uint8_t g[32], v[32];
map_to_curve_curve25519_elligator2(g, v, u_bytes);
EXPECT_EQ(Bytes(g), Bytes(expected_g));
}
#endif
} // namespace