You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/crypto/tests/test_check_monero.h

1130 lines
38 KiB

#if USE_MONERO
START_TEST(test_xmr_base58) {
static const struct {
uint64_t tag;
char *v1;
char *v2;
} tests[] = {
{0x12,
"3bec484c5d7f0246af520aab550452b5b6013733feabebd681c4a60d457b7fc12d5918e"
"31d3c003da3c778592c07b398ad6f961a67082a75fd49394d51e69bbe",
"43tpGG9PKbwCpjRvNLn1jwXPpnacw2uVUcszAtgmDiVcZK4VgHwjJT9BJz1WGF9eMxSYASp"
"8yNMkuLjeQfWqJn3CNWdWfzV"},
{0x12,
"639050436fa36c8288706771412c5972461578d564188cd7fc6f81d6973d064fa461afe"
"66fb23879936d7225051bebbf7f3ae0c801a90bb99fbb346b2fd4d702",
"45PwgoUKaDHNqLL8o3okzLL7biv7GqPVmd8LTcTrYVrMEKdSYwFcyJfMLSRpfU3nh8Z2m81"
"FJD4sUY3nXCdGe61k1HAp8T1"},
{53,
"5a10cca900ee47a7f412cd661b29f5ab356d6a1951884593bb170b5ec8b6f2e83b1da41"
"1527d062c9fedeb2dad669f2f5585a00a88462b8c95c809a630e5734c",
"9vacMKaj8JJV6MnwDzh2oNVdwTLJfTDyNRiB6NzV9TT7fqvzLivH2dB8Tv7VYR3ncn8vCb3"
"KdNMJzQWrPAF1otYJ9cPKpkr"},
};
uint8_t rawn[512];
char strn[512];
int r;
uint64_t tag;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
const char *raw = tests[i].v1;
const char *str = tests[i].v2;
const size_t len = strlen(raw) / 2;
memcpy(rawn, fromhex(raw), len);
r = xmr_base58_addr_encode_check(tests[i].tag, rawn, len, strn,
sizeof(strn));
ck_assert_uint_eq((size_t)r, strlen(str));
ck_assert_mem_eq(strn, str, r);
r = xmr_base58_addr_decode_check(strn, r, &tag, rawn, len);
ck_assert_uint_eq((size_t)r, len);
ck_assert_mem_eq(rawn, fromhex(raw), len);
}
}
END_TEST
START_TEST(test_xmr_getset256_modm) {
static const struct {
uint64_t val;
int r;
char *a;
} tests[] = {
{0x0, 1,
"0000000000000000000000000000000000000000000000000000000000000000"},
{0x7fffffffULL, 1,
"ffffff7f00000000000000000000000000000000000000000000000000000000"},
{0x7fffffffffffffffULL, 1,
"ffffffffffffff7f000000000000000000000000000000000000000000000000"},
{0xdeadc0deULL, 1,
"dec0adde00000000000000000000000000000000000000000000000000000000"},
{0x0, 0,
"dec0adde000000000000000000000000000000000000000000000000000000ff"},
{0x0, 0,
"ffffffffffffffffff0000000000000000000000000000000000000000000000"},
};
uint8_t rawn[32];
uint64_t v1;
bignum256modm a1 = {0};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
int get_res = tests[i].r;
if (get_res) {
set256_modm(a1, tests[i].val);
ck_assert_int_eq(get256_modm(&v1, a1), 1);
ck_assert(v1 == tests[i].val);
contract256_modm(rawn, a1);
ck_assert_mem_eq(rawn, fromhex(tests[i].a), 32);
} else {
expand256_modm(a1, fromhex(tests[i].a), 32);
ck_assert_int_eq(get256_modm(&v1, a1), 0);
}
}
}
END_TEST
START_TEST(test_xmr_cmp256_modm) {
static const struct {
char *a;
char *b;
int res_eq;
int res_cmp;
int res_is_zero_a;
} tests[] = {
{"0000000000000000000000000000000000000000000000000000000000000000",
"0000000000000000000000000000000000000000000000000000000000000000", 1, 0,
1},
{"0000000000000000000000000000000000000000000000000000000000000000",
"0100000000000000000000000000000000000000000000000000000000000000", 0,
-1, 1},
{"dec0adde00000000000000000000000000000000000000000000000000000000",
"dec0adde00000000000000000000000000000000000000000000000000000000", 1, 0,
0},
{"863346d8863c461cde2ec7c2759352c2b952228f33a86ca06bb79574bbe5c30d",
"3ddbd65a6d3ba5e2ab120603685a353a27ce3fd21dfdbea7952d2dd26f1ca00a", 0, 1,
0},
{"f7667f392edbea6e224b1aa9fbf2a3b238b4f977fb4a8f39130cc45f49b5c40a",
"b41b9b1e7e80be71cf290ed4bded58924086b8ac6bdfa1faa0c80c255f074d07", 0, 1,
0},
{"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27501",
"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", 0,
-1, 0},
{"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504",
"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504", 1, 0,
0},
{"0e4005c7826de8f9978749903f40efd140e4ae6d3bed09e558fcce8367b27504",
"0e4005c7826de8f9978749903f41efd140e4ae6d3bed09e558fcce8367b27504", 0,
-1, 0},
};
bignum256modm a1 = {0}, a2 = {0};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(a1, fromhex(tests[i].a), 32);
expand256_modm(a2, fromhex(tests[i].b), 32);
ck_assert_int_eq(eq256_modm(a1, a2), tests[i].res_eq);
ck_assert_int_eq(cmp256_modm(a1, a2), tests[i].res_cmp);
ck_assert_int_eq(iszero256_modm(a1), tests[i].res_is_zero_a);
}
}
END_TEST
START_TEST(test_xmr_copy_check_modm) {
static const struct {
int check;
char *a;
} tests[] = {
{0, "0000000000000000000000000000000000000000000000000000000000000000"},
{1, "ffffff7f00000000000000000000000000000000000000000000000000000000"},
{1, "ffffffffffffff7f000000000000000000000000000000000000000000000000"},
{1, "dec0adde00000000000000000000000000000000000000000000000000000000"},
{0, "dec0adde000000000000000000000fffffffffffffffffffffffffffffffffff"},
};
bignum256modm a1 = {0}, a2 = {0};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand_raw256_modm(a1, fromhex(tests[i].a));
copy256_modm(a2, a1);
ck_assert_int_eq(eq256_modm(a1, a2), 1);
ck_assert_int_eq(check256_modm(a1), tests[i].check);
}
}
END_TEST
START_TEST(test_xmr_mulsub256_modm) {
static const struct {
char *a;
char *b;
char *c;
char *r;
} tests[] = {
{
"713c199348cf7d14b67ae6265ea49c02c8647f07afcbcb6f8d3254b3db972e02",
"4e48a7b7a03ab1106fdfa9441a03c97c644395a12ac4b8effac7344e0719c200",
"1a5711b8c43bcab0161a620368d82727e1d027dc248f420d9bb4db2486c16405",
"6edcc08aa6ec3a5b3d333b5f826be7de9c268be8aaf9521586fbcccbed3b1c0c",
},
{
"d4ade2c62d34af8cfd9daec6f46bf7e57962a8aa46935cb11fab64fa599b4700",
"22ea7989a9f4d34cd8c9442e03b5062dfe8493757cd18a63411cb1a25e44960f",
"772053e613f0859387badcefeb7fbe551a05b00b9337539c8d72661de5929806",
"a5063258df4520b33e97c0a46d80feeace5c251fc7ef7a938d160b8f25795106",
},
{
"01fd2ef25c8221277a2b6daf1f1642bacb8d6ac0dd4f62731cdd73e26eb77900",
"0611b9357530aa638428002769ce0ad553421e971bea1f10d7009bf26d9af805",
"dfece232068b2f8059ca569f345baaed13ab464eb3bebb99de5625dc90a8cf03",
"85752e62bd8085c7c02d5edeb74969d22f1a5bb34349258d2e96de300176bb07",
},
};
bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(a, fromhex(tests[i].a), 32);
expand256_modm(b, fromhex(tests[i].b), 32);
expand256_modm(c, fromhex(tests[i].c), 32);
expand256_modm(r, fromhex(tests[i].r), 32);
mulsub256_modm(r2, a, b, c);
ck_assert_int_eq(eq256_modm(r, r2), 1);
}
}
END_TEST
START_TEST(test_xmr_muladd256_modm) {
static const struct {
char *a;
char *b;
char *c;
char *r;
} tests[] = {
{
"7c3fd8abfbe2be3739d91679ac8dbda086961b941e0d4a00561f758927d8aa09",
"ac2d8d37e4f344aa4040d0f0fc29d45423ab7e69ecacb94ca9fc36819e0e990e",
"2f03f1bac09bc7d002848b68be069dc98b2db028390ae37e13a5166fcae08105",
"dce113add3392f08e3b38b7d31e237eba5066e5a95a1fdbf755b92d05e1ec70b",
},
{
"6979b70f6198d043f4b14e2069f7b89cc9f09e3465e71d472946443989e0e80c",
"8dd5177bc8d7c5bd58c0be74b336952a73ac259ebb812ac8cd755773c6aab807",
"d7658e508a7454ccfb29e2890d6156ac10e18ebe6e00cc5a2d2d87a5080c7f06",
"51b33f6263772781cdbab26ef48870eaf94899894a437dac39496f15b9d0ae00",
},
{
"ebfdb4eabedb1fb9a45b3204735b0511871e20358392fa16a851c519e3a29b09",
"59d98831e9f9e24260158986c4d4035438de9b8876cc11bdcf4c364c75f72908",
"93bce4764eee97dc67f2e37da40bc5641f2cdc637285d273287a3d4383b68f02",
"21547ca6855c85d5adcd673b9d801d0cb0f10dced8f8b68a8c2f74163defde0e",
},
};
bignum256modm a = {0}, b = {0}, c = {0}, r = {0}, r2 = {0};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(a, fromhex(tests[i].a), 32);
expand256_modm(b, fromhex(tests[i].b), 32);
expand256_modm(c, fromhex(tests[i].c), 32);
expand256_modm(r, fromhex(tests[i].r), 32);
muladd256_modm(r2, a, b, c);
ck_assert_int_eq(eq256_modm(r, r2), 1);
}
}
END_TEST
START_TEST(test_xmr_curve25519_set) {
static const struct {
uint32_t val;
char *a;
} tests[] = {
{0x0, "0000000000000000000000000000000000000000000000000000000000000000"},
{0x1, "0100000000000000000000000000000000000000000000000000000000000000"},
{0xdeadc0deUL,
"dec0adde00000000000000000000000000000000000000000000000000000000"},
};
unsigned char buff[32];
bignum25519 a = {0};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
curve25519_set(a, tests[i].val);
curve25519_contract(buff, a);
ck_assert_mem_eq(buff, fromhex(tests[i].a), 32);
}
}
END_TEST
START_TEST(test_xmr_curve25519_consts) {
char *d = "a3785913ca4deb75abd841414d0a700098e879777940c78c73fe6f2bee6c0352";
char *d2 = "59f1b226949bd6eb56b183829a14e00030d1f3eef2808e19e7fcdf56dcd90624";
char *sqrtneg1 =
"b0a00e4a271beec478e42fad0618432fa7d7fb3d99004d2b0bdfc14f8024832b";
unsigned char buff[32];
bignum25519 a = {0};
curve25519_set_d(a);
curve25519_contract(buff, a);
ck_assert_mem_eq(buff, fromhex(d), 32);
curve25519_set_2d(a);
curve25519_contract(buff, a);
ck_assert_mem_eq(buff, fromhex(d2), 32);
curve25519_set_sqrtneg1(a);
curve25519_contract(buff, a);
ck_assert_mem_eq(buff, fromhex(sqrtneg1), 32);
}
END_TEST
START_TEST(test_xmr_curve25519_tests) {
static const struct {
char *a;
int res_neg;
int res_nonzero;
} tests[] = {
{
"0000000000000000000000000000000000000000000000000000000000000000",
0,
0,
},
{
"0100000000000000000000000000000000000000000000000000000000000000",
1,
1,
},
{
"05737aa6100ee54283dc0d483b8e39e61846f6b3736908243d0c824d250b3139",
1,
1,
},
{
"95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15",
1,
1,
},
{
"02587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15",
0,
1,
},
};
bignum25519 a = {0};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
curve25519_expand(a, fromhex(tests[i].a));
ck_assert_int_eq(curve25519_isnegative(a), tests[i].res_neg);
ck_assert_int_eq(curve25519_isnonzero(a), tests[i].res_nonzero);
}
}
END_TEST
START_TEST(test_xmr_curve25519_expand_reduce) {
static const struct {
char *a;
char *b;
} tests[] = {
{"dec0adde00000000000000000000000000000000000000000000000000000000",
"dec0adde00000000000000000000000000000000000000000000000000000000"},
{"95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15",
"95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc15"},
{"95587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bcff",
"a8587a5ef6900fa8e32d6a41bd8090b1e33e694284323d1d1f02d69865f2bc7f"},
{"95587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bcff",
"a8587a5ef6900fa8e32d6affbd8090b1e33e694284323fffff02d69865f2bc7f"},
};
unsigned char buff[32];
bignum25519 a = {0};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
curve25519_expand_reduce(a, fromhex(tests[i].a));
curve25519_contract(buff, a);
ck_assert_mem_eq(buff, fromhex(tests[i].b), 32);
}
}
END_TEST
START_TEST(test_xmr_ge25519_base) {
unsigned char buff[32];
char *base =
"5866666666666666666666666666666666666666666666666666666666666666";
ge25519 b;
ge25519_set_base(&b);
ge25519_pack(buff, &b);
ck_assert_mem_eq(buff, fromhex(base), 32);
}
END_TEST
START_TEST(test_xmr_ge25519_check) {
static const struct {
char *x;
char *y;
char *z;
char *t;
int r;
} tests[] = {
{"4ff97748221f954414f836d84e8e7e207786bcd20eb67044756dca307e792c60",
"2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63",
"0100000000000000000000000000000000000000000000000000000000000000",
"3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 1},
{"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c",
"ca48045f790145a1eec3946dfd73747fde0fdb4238607e0a203f8ef5bef90e0e",
"0100000000000000000000000000000000000000000000000000000000000000",
"6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 1},
{"4ff97748221f954414f836d84e8e7e207786bcd20eb6704475ffca307e792c60",
"2c7be86ab07488ba43e8e03d85a67625cfbf98c8544de4c877241b7aaafc7f63",
"0100000000000000000000000000000000000000000000000000000000000000",
"3ec65b03954ce7432525b9b3f4a9f5747f57b40903d1bf8892527366325fe036", 0},
{"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c",
"ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e",
"0100000000000000000000000000000000000000000000000000000000000000",
"6c5e5cbae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0},
{"358fd25e4b84397d207e23cf3a75819bd6b2254cabc990b31ad63873cc38fc7c",
"ca48045f790145a1eec3946dfd73747fdfffdb4238607e0a203f8ef5bef90e0e",
"0100000000000000000000000000000000000000000000000000000000000000",
"6c5e5ffae4b05e149d0aca50bf7b4112acbbe6233ace9c8bd5bcedf34df9ce0b", 0},
};
struct ge25519_t p;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
curve25519_expand_reduce(p.x, fromhex(tests[i].x));
curve25519_expand_reduce(p.y, fromhex(tests[i].y));
curve25519_expand_reduce(p.z, fromhex(tests[i].z));
curve25519_expand_reduce(p.t, fromhex(tests[i].t));
ck_assert_int_eq(ge25519_check(&p), tests[i].r);
}
}
END_TEST
START_TEST(test_xmr_ge25519_scalarmult_base_wrapper) {
static const struct {
char *sc;
char *pt;
} tests[] = {
{
"40be740e26bd1c84f5a8fec737c0ed30e87bd45adfcd91e320f8dfb68b1a870e",
"b7a8b2f3dbfd41b38d20aec733a316dbfc2633503799cd36f38570cafc8ea887",
},
{
"1b3746add992215d427e43a58354c11ff9e6dfa1c187250938f7f9334fa41d05",
"e2a1bfbe38a9749fe6ede79d923b778fa4c89393473d633bec01fa68617d0828",
},
{
"69af25c54090a9746d3f6043348452429ffd53c1530fa114fd0055b70d61020f",
"6bf1783b0a7495d5f6c36605dca95e723ca120a306c255084787f09b12771124",
},
{
"0000000000000000000000000000000000000000000000000000000000000000",
"0100000000000000000000000000000000000000000000000000000000000000",
},
{
"0100000000000000000000000000000000000000000000000000000000000000",
"5866666666666666666666666666666666666666666666666666666666666666",
},
{
"0800000000000000000000000000000000000000000000000000000000000000",
"b4b937fca95b2f1e93e41e62fc3c78818ff38a66096fad6e7973e5c90006d321",
},
{
"ffffffffffffffff000000000000000000000000000000000000000000000000",
"e185757a3fdc6519a6e7bebd97aa52bdc999e4c87d5c3aad0d995763ab6c6985",
},
};
ge25519 pt, pt2;
bignum256modm sc;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(sc, fromhex(tests[i].sc), 32);
ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
ge25519_scalarmult_base_wrapper(&pt2, sc);
ck_assert_int_eq(ge25519_eq(&pt, &pt2), 1);
}
}
END_TEST
START_TEST(test_xmr_ge25519_scalarmult) {
static const struct {
char *sc;
char *pt;
char *pt2;
} tests[] = {
{
"0000000000000000000000000000000000000000000000000000000000000000",
"5cbb3b2784c16f0e7eb4f2a7f93288552bb24ec51c5e01504c1e6885cfbca6d0",
"0100000000000000000000000000000000000000000000000000000000000000",
},
{
"0100000000000000000000000000000000000000000000000000000000000000",
"f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6",
"f39b6770008d069acb92eb95329dec2cb0054da024e437a1bdf1ae06527deff6",
},
{
"3930000000000000000000000000000000000000000000000000000000000000",
"2835b3983e3cc01a640fd188bf6bbbafbf997a3344d800eed22e4e82a412941c",
"2fe8b2dd0f23e02fca6989e170135584d684583c0a44f6a7d3ebd964685d36c7",
},
{
"ffffffffffffffff000000000000000000000000000000000000000000000000",
"bb8af7a53a8f1b477c810e833a84cdc789a6b81a6b6417be4f97ffd9ae0fe0b8",
"3a5c9a7dacca9dd8827881f38c36aad7d402a5efc2cab58c7553b903876e1491",
},
{
"864203a09e1c788a482685c739af07355ebb2c840b7de6af87eff5f19ee3b807",
"d404a9bbf351e7320ea6d11cdeeccaf505f706731cb5e5d839b950edb7ba6286",
"11e09c89e0be7663e0e2d4a01fb05d6a3fd84a78a6fa4fd7daaacf2d19311a38",
},
{
"3e01f05920a238e33766814d10f0c3a3e975072399ad90a823d4808db1d85209",
"52a2d35798a0ac209b8fa194fe398b869aba5f20d80ee3d8ca77759a8e0bae0d",
"4256addc2f036150f3fdc0a7905f01285239d6dd4eecc4be8e3b134eef4639fe",
},
{
"ad63d591716a9e89a024a074bc6ce661268d1bb3665f91e8b981f189b1a49507",
"3928bde7a92e1341c3dfee35a66fa5639204f5b9747963278af430145028648d",
"9c959003ba91004956df98800a5024d94031db5ac659675b26350657d93c34f9",
},
};
ge25519 pt, pt2, pt3;
bignum256modm sc;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(sc, fromhex(tests[i].sc), 32);
ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
ge25519_unpack_vartime(&pt2, fromhex(tests[i].pt2));
ge25519_scalarmult(&pt3, &pt, sc);
ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1);
}
}
END_TEST
START_TEST(test_xmr_ge25519_ops) {
int tests[] = {1, 2, 7, 8, 637, 9912, 12345};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
struct ge25519_t a, b, c, d;
bignum256modm s1 = {0}, s2 = {0}, s3 = {0}, s4 = {0};
set256_modm(s1, tests[i]);
set256_modm(s2, 8 * tests[i]);
set256_modm(s3, 8);
set256_modm(s4, 2);
ge25519_scalarmult_base_niels(&a, ge25519_niels_base_multiples, s1);
ge25519_scalarmult_base_niels(&b, ge25519_niels_base_multiples, s2);
ge25519_scalarmult(&c, &a, s4);
ge25519_scalarmult(&c, &c, s4);
ge25519_scalarmult(&c, &c, s4);
ck_assert_int_eq(ge25519_eq(&c, &b), 1);
ck_assert_int_eq(ge25519_eq(&a, &b), 0);
ge25519_scalarmult_base_wrapper(&a, s1);
ge25519_mul8(&b, &a);
ge25519_scalarmult_base_wrapper(&c, s2);
ck_assert_int_eq(ge25519_eq(&b, &c), 1);
ge25519_scalarmult(&d, &a, s3);
ck_assert_int_eq(ge25519_eq(&d, &c), 1);
ge25519_copy(&a, &b);
ge25519_neg_full(&b);
ck_assert_int_eq(ge25519_eq(&b, &c), 0);
ge25519_add(&c, &a, &b, 0);
set256_modm(s2, 0);
ge25519_scalarmult_base_wrapper(&a, s2);
ck_assert_int_eq(ge25519_eq(&a, &c), 1);
}
}
END_TEST
START_TEST(test_xmr_check_point) {
static const struct {
char *p;
bool on;
} tests[] = {
{"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608",
true},
{"54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5",
true},
{"bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808",
true},
{"00000000000000c60073ec000000000000ff0000000000000000000000000080",
false},
{"00000000000000004e0000000000000000000000000000000000000000000000",
false},
{"0000008b0000000000000000b200000000000000000000000000000000000080",
false},
{"a0953eebe2f676256c37af4f6f84f32d397aaf3b73606e96c5ddfcecbb1ceec8",
false},
{"a82cd837efee505ec8425769ea925bee869ec3c78a57708c64c2ef2bd6ad3b88",
false},
{"031c56cfc99758f6f025630e77c6dea0b853c3ab0bf6cf8c8dab03d1a4618178",
false},
};
ge25519 tmp;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
int res = ge25519_unpack_negative_vartime(&tmp, fromhex(tests[i].p));
ck_assert_int_eq(ge25519_check(&tmp), tests[i].on);
ck_assert_int_eq(res, tests[i].on);
}
}
END_TEST
START_TEST(test_xmr_h) {
char *H = "8b655970153799af2aeadc9ff1add0ea6c7251d54154cfa92c173a0dd39c1f94";
ge25519 H2, Z;
ge25519_p1p1 P_11;
ge25519_pniels P_ni;
uint8_t buff[32] = {0};
ge25519_pack(buff, &xmr_h);
ck_assert_mem_eq(buff, fromhex(H), 32);
int res = ge25519_unpack_vartime(&H2, buff);
ck_assert_int_eq(res, 1);
ck_assert_int_eq(ge25519_eq(&xmr_h, &xmr_h), 1);
ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1);
res = ge25519_unpack_negative_vartime(&H2, buff);
ck_assert_int_eq(res, 1);
ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 0);
ge25519_neg_full(&H2);
ck_assert_int_eq(ge25519_eq(&H2, &xmr_h), 1);
ge25519_full_to_pniels(&P_ni, &xmr_h);
ge25519_pnielsadd_p1p1(&P_11, &H2, &P_ni, 1);
ge25519_p1p1_to_full(&H2, &P_11);
ge25519_set_neutral(&Z);
ck_assert_int_eq(ge25519_eq(&Z, &H2), 1);
}
END_TEST
START_TEST(test_xmr_fast_hash) {
uint8_t hash[32];
char tests[][2][65] = {
{"", "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"},
{"00",
"bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a"},
{"000102",
"f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"},
{"000102030405",
"51e8babe8b42352100dffa7f7b3843c95245d3d545c6cbf5052e80258ae80627"},
{"000102030406",
"74e7a0111ee2390dc68269a549a76dcfb553ca1260035eae982d669ff6494f32"},
{"000102030407",
"3a81c5d02a87786343f88414aae150a09f6933b1d3bb660d0a9ac54e12e5cd86"},
{"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64",
"7fb4d1c8e32f7414fe8c7b2774ec05bff6845e4278565d17f95559513a244da2"},
{"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05",
"2998fe52f8b9883149babd9c546912c3edfbd3cd98896a0e57b1b5929fa5ff7b"},
};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
xmr_fast_hash(hash, fromhex(tests[i][0]), strlen(tests[i][0]) / 2);
ck_assert_mem_eq(hash, fromhex(tests[i][1]), 32);
}
}
END_TEST
START_TEST(test_xmr_hasher) {
Hasher hasher;
uint8_t hash[32];
static const struct {
char *chunk[3];
char *hash;
} tests[] = {
{{"00", "01", "02"},
"f84a97f1f0a956e738abd85c2e0a5026f8874e3ec09c8f012159dfeeaab2b156"},
{{"001122334455667788", "00", ""},
"72a228ee8d0d01c815f112ce315cfc215a0594abcec24162304ae0ffda139d9e"},
{{"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608", "",
"00112233445566"},
"c3deafd96ff10cc190c6024548c344f6401cfe5151ab2fcd40df7cc501147e01"},
};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
xmr_hasher_init(&hasher);
for (int j = 0; j < 3; j++) {
xmr_hasher_update(&hasher, fromhex(tests[i].chunk[j]),
strlen(tests[i].chunk[j]) / 2);
}
xmr_hasher_final(&hasher, hash);
ck_assert_mem_eq(hash, fromhex(tests[i].hash), 32);
}
}
END_TEST
START_TEST(test_xmr_hash_to_scalar) {
bignum256modm a1;
unsigned char out[32];
char tests[][2][65] = {
{"", "4a078e76cd41a3d3b534b83dc6f2ea2de500b653ca82273b7bfad8045d85a400"},
{"00",
"5497c9b6a7059553835f85118dc089d66512f7b477d66591ff96a9e064bcc90a"},
{"000102",
"5727ca206dbafa2e099b022ed528f5bdf7874e3ec09c8f012159dfeeaab2b106"},
{"000102030405",
"7740cf04577c107153a50b3abe44859f5245d3d545c6cbf5052e80258ae80607"},
{"000102030406",
"ad6bbffaceb8020543ac82bcadb9d090b553ca1260035eae982d669ff6494f02"},
{"000102030407",
"d2e116e9576ee5a29011c8fcb41259f99e6933b1d3bb660d0a9ac54e12e5cd06"},
{"259ef2aba8feb473cf39058a0fe30b9ff6d245b42b6826687ebd6b63128aff64",
"3d6d3727dc50bca39e6ccfc9c12950eef5845e4278565d17f95559513a244d02"},
{"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05",
"aecc45c83f0408c96c70f8273e94f930edfbd3cd98896a0e57b1b5929fa5ff0b"},
};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
xmr_hash_to_scalar(a1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2);
contract256_modm(out, a1);
ck_assert_mem_eq(out, fromhex(tests[i][1]), 32);
}
}
END_TEST
START_TEST(test_xmr_hash_to_ec) {
ge25519 p1;
unsigned char out[32];
char tests[][2][65] = {
{"", "d6d7d783ab18e1be65586adb7902a4175b737ef0b902875e1d1d5c5cf0478c0b"},
{"00",
"8e2fecb36320bc4e192e10ef54afc7c83fbeb0c38b7debd4fea51301f0bd4f3d"},
{"000102",
"73b233e2e75d81b9657a857e38e7ab2bc3600e5c56622b9fe4b976ff312220fa"},
{"000102030405",
"bebe3c84092c0f7a92704cafb16562cc45c47f45e84baec8d4bba3559d1c1808"},
{"000102030406",
"525567a6a40a94f2d916bc1efea234bbd3b9162403ec2faba871a90f8d0d487e"},
{"000102030407",
"99b1be2a92cbd22b24b48fb7a9daadd4d13a56915c4f6ed696f271ad5bdbc149"},
{"42f6835bf83114a1f5f6076fe79bdfa0bd67c74b88f127d54572d3910dd09201",
"54863a0464c008acc99cffb179bc6cf34eb1bbdf6c29f7a070a7c6376ae30ab5"},
{"44caa1c26187afe8dacc5d91cb8a51282334d9308a818fe4d3607275e2a61f05",
"001000a93e0e6937b4feaf079e418a028ca85459aa39ac3871b94076f88ca608"},
};
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
xmr_hash_to_ec(&p1, fromhex(tests[i][0]), strlen(tests[i][0]) / 2);
ge25519_pack(out, &p1);
ck_assert_mem_eq(out, fromhex(tests[i][1]), 32);
}
}
END_TEST
START_TEST(test_xmr_derivation_to_scalar) {
static const struct {
char *pt;
uint32_t idx;
char *sc;
} tests[] = {
{
"c655b2d9d2670a1c9f26f7586b6d6b1ec5173b8b33bca64c3d305a42d66738b1",
0,
"ca7ce31b273dd1ac00dc3553e654fb66036804800e27c826bd2b78649243900b",
},
{
"2b1dbd7a007dcc4d729fa8359705595599737fcef60afb36b379fe033095dca7",
1,
"60afd5a63b14845d3b92d16eac386713e4ff617fdc5c1a07c3212098c1f5610c",
},
{
"a48ed3797225dab4b4316b5e40107b6bd63e5f4dc517ba602774d703576ec771",
24,
"fe81804091e50a5c2233faa6277360fbe1948ea15dddbae62c1d40bbd1918606",
},
{
"fa27b5b39741f5341b4e89269e3a05ff7e76ec7739843872468fc4bec8475410",
65537,
"1ba36841f57aa8b799c4dd02b39d53e5fb7780d3f09f91a57a86dcb418d8d506",
},
};
ge25519 pt;
bignum256modm sc, sc2;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(sc, fromhex(tests[i].sc), 32);
ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
xmr_derivation_to_scalar(sc2, &pt, tests[i].idx);
ck_assert_int_eq(eq256_modm(sc, sc2), 1);
xmr_derivation_to_scalar(sc2, &pt, tests[i].idx + 1);
ck_assert_int_eq(eq256_modm(sc, sc2), 0);
}
}
END_TEST
START_TEST(test_xmr_generate_key_derivation) {
static const struct {
char *pt;
char *sc;
char *r;
} tests[] = {
{
"38f94f27c8037aff025e365275ed1029fd636dda5f69e5f98fdcf92e0a28f31a",
"8f1c73ee5327a43264a7b60b9e7882312b582f33e89846a8694dbf094bb3a90a",
"1fbfe4dcc8c824c274649545f297fa320cd4c1689b1d0ff4887567c4d4a75649",
},
{
"26785c3941a32f194228eb659c5ee305e63868896defc50ee6c4e0e92d1e246a",
"dbbffec4686ba8ab25e2f1b04c0e7ae51c5143c91353bfb5998430ebe365a609",
"cca34db8dd682ec164d8973b555253934596b77849ef7709d9321121c25aba02",
},
{
"43505a8ce7248f70d3aae4f57fb59c254ce2b2a0cc2bcf50f2344e51d59b36b3",
"19a802e35f6ff94efe96ec016effe04e635bbd9c1ce2612d5ba2ee4659456b06",
"fc6c93a93f77ff89c18b9abf95b28ec8591ab97eee8e4afee93aa766a4bd3934",
},
};
ge25519 pt, pt2, pt3;
bignum256modm sc;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(sc, fromhex(tests[i].sc), 32);
ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
ge25519_unpack_vartime(&pt2, fromhex(tests[i].r));
xmr_generate_key_derivation(&pt3, &pt, sc);
ck_assert_int_eq(ge25519_eq(&pt3, &pt2), 1);
ck_assert_int_eq(ge25519_eq(&pt3, &pt), 0);
}
}
END_TEST
START_TEST(test_xmr_derive_private_key) {
static const struct {
char *pt;
uint32_t idx;
char *base;
char *r;
} tests[] = {
{
"0541d8f069e5e80a892e39bbf1944ef578008cf9ecf1d100760a05858c1b709e",
0,
"76967eeb0a3d181bb0b384be71c680a4287599f27b2ddbd07f8e06ab6f2c880e",
"45728c5cb658e470790f124a01699d2126832b7e5c6b7760b6f11119b96ad603",
},
{
"fc6e0bd785a84e62c9ac8a97e0e604a79494bc2cf7b3b38ef8af7791c87b5bb8",
1,
"32fbe149562b7ccb34bc4105b87b2a834024799336c8eea5e94df77f1ae9a807",
"64508e83bbadf63f8ecfae4d9dcdd39a4ba23508a545e1a37026f0fa2539d601",
},
{
"f6bd7a72dc9444dc7e09a0eb4d312d36fe173693d6405b132a5b090297a04ea9",
65537,
"333a8fcce6726457e4222a87b9b475c1fcf985f756c2029fcb39184c0a5c4804",
"37c16a22da4c0082ebf4bf807403b169f75142a9bd8560ed45f3f9347218260e",
},
};
ge25519 pt;
bignum256modm base, res, res_exp;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(base, fromhex(tests[i].base), 32);
expand256_modm(res_exp, fromhex(tests[i].r), 32);
ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
xmr_derive_private_key(res, &pt, tests[i].idx, base);
ck_assert_int_eq(eq256_modm(res, res_exp), 1);
ck_assert_int_eq(eq256_modm(res, base), 0);
}
}
END_TEST
START_TEST(test_xmr_derive_public_key) {
static const struct {
char *pt;
uint32_t idx;
char *base;
char *r;
} tests[] = {
{
"653f03e7766d472826aa49793bc0cfde698e6745ae5e4217980ba307739f2ed9",
0,
"2a393f0858732970ac8dea003b17e1ce9371f0a045bd9b7af0d998262739f4cc",
"f7a3db27c45f265f6a68a30137ca44289a6cf1a6db2cf482c59ebfb0142ad419",
},
{
"338e93f61e6470a5cc71c07b8caedd1a9a28da037aab65c1ca5538501b012c81",
1,
"af3a1d39397d778731c4510110fd117dc02f756e390713d58f94a06203ce39eb",
"779e2a043c881f06aba1952741fd753098615c4fafa8f62748467ab9bac43241",
},
{
"7735e9476440927b89b18d7a1e0645b218a1a6d28c642aebb16c1dba0926d5e4",
65537,
"62c3eed062bd602f7f2164c69ad0b5a8eb3ea560c930f6b41abfc1c4839ea432",
"6da4ebd29498d16c4e813abb3e328c83f9b01a7ba1da6e818071f8ec563626c8",
},
};
ge25519 pt, base, res, res_exp;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
ge25519_unpack_vartime(&pt, fromhex(tests[i].pt));
ge25519_unpack_vartime(&base, fromhex(tests[i].base));
ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r));
xmr_derive_public_key(&res, &pt, tests[i].idx, &base);
ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
ck_assert_int_eq(ge25519_eq(&res, &base), 0);
}
}
END_TEST
START_TEST(test_xmr_add_keys2) {
static const struct {
char *a;
char *b;
char *B;
char *r;
} tests[] = {
{
"631238da9578d7cb8db16fc4322671bfcb251cc5228b060664800ec1895be608",
"f9a73fca0be058415a148f9e2871be59e1fc7ae6f6193199125237e0d7c1630f",
"ef5ca4fc90f330e825adcdc953da0b3becd853aa819219842790bb39775f2255",
"06623fd0e7a3d787a4d224f6ca2fdab2dcd9d1221578515974b9c4dee65fdcf5",
},
{
"dac2e629e5c75c312253b19d1d3a0a423158fdd9cdcf4c7a7bf2717d0b748602",
"0483d98d750d4977b499cefd558a0a61580823a37da2b011501e24718e6c7f0a",
"51fd3cd2f1a603ec7be3b35da9c105d91c4304e6a63facf48d7730712cedc0ee",
"f7a5d645ba01a5b7ccbe9636d14422bb587fc529317b23761f0e39222b783b87",
},
{
"817c4d2fd3e841d860bdab6b7ccf098f3e637eca468d0a3825c50b71f61d0e0c",
"1f6c4795d7fb0d53b5775874ac4c0963607d2b7bd11a7c5d10735badc4a27207",
"bef0e0ed09d602bbe1dd38358b5f8fca27fcad60a69440f104441c3fc68df9c7",
"bc0fc824d74eca0e10eacd0bc2f3322e0bcb02a44ce53f2f5f1fc472f99be8d2",
},
};
bignum256modm a, b;
ge25519 B, res, res_exp;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(a, fromhex(tests[i].a), 32);
expand256_modm(b, fromhex(tests[i].b), 32);
ge25519_unpack_vartime(&B, fromhex(tests[i].B));
ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r));
xmr_add_keys2(&res, a, b, &B);
ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
ck_assert_int_eq(ge25519_eq(&res, &B), 0);
xmr_add_keys2_vartime(&res, a, b, &B);
ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
ck_assert_int_eq(ge25519_eq(&res, &B), 0);
}
}
END_TEST
START_TEST(test_xmr_add_keys3) {
static const struct {
char *a;
char *A;
char *b;
char *B;
char *r;
} tests[] = {
{
"7048b8c4603ae194c502fa458b0e11a4c7a330852bbef66b7c1d67e9f919f509",
"9167c5b182758699baeb421e7f1200272fc775e4c7c7c183cc47261dccbb569f",
"c2cb2bc0249fc7be8eb9b3bed7d37aa6f2c3f433abb3a4a00b13bed64b61f30b",
"b3ec53b07a1be70ac8d0fa365b86f0d6d4cbf98641e7704b3d684558e2ea59ef",
"4dc016d702d599bde5eaeb2bf0c2d0d3f6b9cede961bc539bcb369c3b3086358",
},
{
"e9794a6652940474958936f07f3904d514228553247633cfb7ae8ffa9fa0f406",
"0e51cea6df2f6f56a9935689364f0d295a7c89f51d40efb2518c17d1b9db792b",
"c132e7be08afdd93984c52c6e1c596edc6b8fc8f1faed95f55e2f819ee806706",
"1a0e03c6858f6cf1b43f4b8456c03144af553bbbd050e152834fd1615b577cb3",
"088f19c6727f8704373d391a36c230395d386f69edb4151ecf8afcd27793fff5",
},
{
"88920b0c96b15cc04e879f53a76f85f3c7a2a5f275b2772b5b74ee83372aea00",
"e95731ab61a98fedcded475cf21b4ecf2ef9f1adecefba8fdc476a5bb1cf60f9",
"c86026b66c1045fb69e4f24ff6c15d4fad4d565e646938a2ffb7db37ccb4100d",
"d80cbf2986c12e4c7ebac1e55abbdfc4212c00aec8bc90c965becf863262a074",
"047cebaeb3ec2132e7386ba52531b04070206ba1106565c0fbd7d7280694568a",
},
};
bignum256modm a, b;
ge25519 A, B, res, res_exp;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(a, fromhex(tests[i].a), 32);
expand256_modm(b, fromhex(tests[i].b), 32);
ge25519_unpack_vartime(&A, fromhex(tests[i].A));
ge25519_unpack_vartime(&B, fromhex(tests[i].B));
ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r));
xmr_add_keys3(&res, a, &A, b, &B);
ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
ck_assert_int_eq(ge25519_eq(&res, &B), 0);
xmr_add_keys3_vartime(&res, a, &A, b, &B);
ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
ck_assert_int_eq(ge25519_eq(&res, &B), 0);
}
}
END_TEST
START_TEST(test_xmr_get_subaddress_secret_key) {
static const struct {
uint32_t major, minor;
char *m;
char *r;
} tests[] = {
{
0,
0,
"36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207",
"8a510a9fe1824b49abbae05958084f9c9098775f29e15427309177882471cf01",
},
{
0,
1,
"36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207",
"2bbc9366c04abb0523e2b2d6e709670ffe6645bacedfee968d9c6bc8eefe9c0f",
},
{
100,
100,
"36fad9f7bff465c15a755f1482fb2ecc3a4e434303df906882234e42b5813207",
"c3837d41fedeaed126cf4fc1a5ea47b8b7f38f6a64aa534e3dd45a3c93f37600",
},
};
bignum256modm m, res, res_exp;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(m, fromhex(tests[i].m), 32);
expand256_modm(res_exp, fromhex(tests[i].r), 32);
xmr_get_subaddress_secret_key(res, tests[i].major, tests[i].minor, m);
ck_assert_int_eq(eq256_modm(res, res_exp), 1);
ck_assert_int_eq(eq256_modm(res, m), 0);
}
}
END_TEST
START_TEST(test_xmr_gen_c) {
static const struct {
char *a;
uint64_t amount;
char *r;
} tests[] = {
{
"e3e6558c291bbb98aa691d068b67d59dc520afb23fdd51bf65283626fc2ad903",
0,
"ef19d73bdf3749240b80ee7695f53ad7c2fc2cf868a93209799f41212d099750",
},
{
"6788c9579c377f3228680bd0e6d01b1ee0c763b35ed39d36fa2146cc2ee16e0e",
1,
"4913b9af4f2725d87a4404c22cf366597d1c1e6a1f510ae14081d8b7c5a9de77",
},
{
"ad9e89d67012935540427c241756d6a9d260c5e134603c41d31e24f8651bef08",
65537,
"f005721da08f24e68314abed3ddfd94165e4be3813398fb126e3f366820b9c90",
},
{
"fdbb70ff07be24d98de3bffa0a33756646497224318fb7fe136f0e7789d12607",
0xffffffffffffffffULL,
"a9c38927f299c5f14c98a1a9c9981e59c606ff597274b9b709e1356f12e1498c",
},
};
bignum256modm a;
ge25519 res, res_exp;
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
expand256_modm(a, fromhex(tests[i].a), 32);
ge25519_unpack_vartime(&res_exp, fromhex(tests[i].r));
xmr_gen_c(&res, a, tests[i].amount);
ck_assert_int_eq(ge25519_eq(&res, &res_exp), 1);
}
}
END_TEST
START_TEST(test_xmr_varint) {
static const struct {
uint64_t x;
char *r;
} tests[] = {
{
0,
"00",
},
{
24,
"18",
},
{
65535,
"ffff03",
},
{
65537,
"818004",
},
{
0x7fffffffULL,
"ffffffff07",
},
{
0xffffffffULL,
"ffffffff0f",
},
{
0xffffffffffffffffULL,
"ffffffffffffffffff01",
},
{
0xdeadc0deULL,
"de81b7f50d",
},
};
uint64_t val;
unsigned char buff[64];
for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) {
int s1 = xmr_size_varint(tests[i].x);
int written = 0;
int read = 0;
ck_assert_uint_eq((size_t)s1, strlen(tests[i].r) / 2);
written = xmr_write_varint(buff, sizeof(buff), tests[i].x);
ck_assert_int_eq(s1, written);
ck_assert_mem_eq(buff, fromhex(tests[i].r), strlen(tests[i].r) / 2);
read = xmr_read_varint(buff, sizeof(buff), &val);
ck_assert_int_eq(read, written);
ck_assert(tests[i].x == val);
}
}
END_TEST
#endif