mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-27 08:38:07 +00:00
xmr: monero crypto implemented, tests
This commit is contained in:
parent
1863045da4
commit
4aea73e4bb
7
Makefile
7
Makefile
@ -51,6 +51,11 @@ SRCS += aes/aescrypt.c aes/aeskey.c aes/aestab.c aes/aes_modes.c
|
||||
SRCS += ed25519-donna/curve25519-donna-32bit.c ed25519-donna/curve25519-donna-helpers.c ed25519-donna/modm-donna-32bit.c
|
||||
SRCS += ed25519-donna/ed25519-donna-basepoint-table.c ed25519-donna/ed25519-donna-32bit-tables.c ed25519-donna/ed25519-donna-impl-base.c
|
||||
SRCS += ed25519-donna/ed25519.c ed25519-donna/curve25519-donna-scalarmult-base.c ed25519-donna/ed25519-sha3.c ed25519-donna/ed25519-keccak.c
|
||||
SRCS += ed25519-donna/ge25519.c
|
||||
SRCS += monero/base58.c
|
||||
SRCS += monero/serialize.c
|
||||
SRCS += monero/xmr.c
|
||||
SRCS += monero/range_proof.c
|
||||
SRCS += blake256.c
|
||||
SRCS += blake2b.c blake2s.c
|
||||
SRCS += groestl.c
|
||||
@ -75,7 +80,7 @@ tests: tests/test_check tests/test_openssl tests/test_speed tests/libtrezor-cryp
|
||||
tests/aestst: aes/aestst.o aes/aescrypt.o aes/aeskey.o aes/aestab.o
|
||||
$(CC) $^ -o $@
|
||||
|
||||
tests/test_check.o: tests/test_check_cardano.h tests/test_check_cashaddr.h tests/test_check_segwit.h
|
||||
tests/test_check.o: tests/test_check_cardano.h tests/test_check_monero.h tests/test_check_cashaddr.h tests/test_check_segwit.h
|
||||
|
||||
tests/test_check: tests/test_check.o $(OBJS)
|
||||
$(CC) tests/test_check.o $(OBJS) $(TESTLIBS) -o tests/test_check
|
||||
|
5
base58.c
5
base58.c
@ -29,7 +29,8 @@
|
||||
#include "ripemd160.h"
|
||||
#include "memzero.h"
|
||||
|
||||
static const int8_t b58digits_map[] = {
|
||||
const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
const int8_t b58digits_map[] = {
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
@ -148,8 +149,6 @@ int b58check(const void *bin, size_t binsz, HasherType hasher_type, const char *
|
||||
return binc[0];
|
||||
}
|
||||
|
||||
static const char b58digits_ordered[] = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||
|
||||
bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz)
|
||||
{
|
||||
const uint8_t *bin = data;
|
||||
|
3
base58.h
3
base58.h
@ -29,6 +29,9 @@
|
||||
#include "hasher.h"
|
||||
#include "options.h"
|
||||
|
||||
extern const char b58digits_ordered[];
|
||||
extern const int8_t b58digits_map[];
|
||||
|
||||
int base58_encode_check(const uint8_t *data, int len, HasherType hasher_type, char *str, int strsize);
|
||||
int base58_decode_check(const char *str, HasherType hasher_type, uint8_t *data, int datalen);
|
||||
|
||||
|
378
ed25519-donna/ge25519.c
Normal file
378
ed25519-donna/ge25519.c
Normal file
@ -0,0 +1,378 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 29/04/2018.
|
||||
//
|
||||
|
||||
#include <assert.h>
|
||||
#include "ge25519.h"
|
||||
|
||||
static const uint32_t reduce_mask_25 = (1 << 25) - 1;
|
||||
static const uint32_t reduce_mask_26 = (1 << 26) - 1;
|
||||
|
||||
/* sqrt(x) is such an integer y that 0 <= y <= p - 1, y % 2 = 0, and y^2 = x (mod p). */
|
||||
/* d = -121665 / 121666 */
|
||||
static const bignum25519 ALIGN(16) fe_d = {
|
||||
0x35978a3, 0x0d37284, 0x3156ebd, 0x06a0a0e, 0x001c029, 0x179e898, 0x3a03cbb, 0x1ce7198, 0x2e2b6ff, 0x1480db3}; /* d */
|
||||
static const bignum25519 ALIGN(16) fe_sqrtm1 = {
|
||||
0x20ea0b0, 0x186c9d2, 0x08f189d, 0x035697f, 0x0bd0c60, 0x1fbd7a7, 0x2804c9e, 0x1e16569, 0x004fc1d, 0x0ae0c92}; /* sqrt(-1) */
|
||||
//static const bignum25519 ALIGN(16) fe_d2 = {
|
||||
// 0x2b2f159, 0x1a6e509, 0x22add7a, 0x0d4141d, 0x0038052, 0x0f3d130, 0x3407977, 0x19ce331, 0x1c56dff, 0x0901b67}; /* 2 * d */
|
||||
|
||||
/* A = 2 * (1 - d) / (1 + d) = 486662 */
|
||||
static const bignum25519 ALIGN(16) fe_ma2 = {
|
||||
0x33de3c9, 0x1fff236, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff}; /* -A^2 */
|
||||
static const bignum25519 ALIGN(16) fe_ma = {
|
||||
0x3f892e7, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff, 0x3ffffff, 0x1ffffff}; /* -A */
|
||||
static const bignum25519 ALIGN(16) fe_fffb1 = {
|
||||
0x1e3bdff, 0x025a2b3, 0x18e5bab, 0x0ba36ac, 0x0b9afed, 0x004e61c, 0x31d645f, 0x09d1bea, 0x102529e, 0x0063810}; /* sqrt(-2 * A * (A + 2)) */
|
||||
static const bignum25519 ALIGN(16) fe_fffb2 = {
|
||||
0x383650d, 0x066df27, 0x10405a4, 0x1cfdd48, 0x2b887f2, 0x1e9a041, 0x1d7241f, 0x0612dc5, 0x35fba5d, 0x0cbe787}; /* sqrt(2 * A * (A + 2)) */
|
||||
static const bignum25519 ALIGN(16) fe_fffb3 = {
|
||||
0x0cfd387, 0x1209e3a, 0x3bad4fc, 0x18ad34d, 0x2ff6c02, 0x0f25d12, 0x15cdfe0, 0x0e208ed, 0x32eb3df, 0x062d7bb}; /* sqrt(-sqrt(-1) * A * (A + 2)) */
|
||||
static const bignum25519 ALIGN(16) fe_fffb4 = {
|
||||
0x2b39186, 0x14640ed, 0x14930a7, 0x04509fa, 0x3b91bf0, 0x0f7432e, 0x07a443f, 0x17f24d8, 0x031067d, 0x0690fcc}; /* sqrt(sqrt(-1) * A * (A + 2)) */
|
||||
|
||||
void curve25519_set(bignum25519 r, uint32_t x){
|
||||
r[0] = x & reduce_mask_26; x >>= 26;
|
||||
r[1] = x & reduce_mask_25;
|
||||
r[2] = 0;
|
||||
r[3] = 0;
|
||||
r[4] = 0;
|
||||
r[5] = 0;
|
||||
r[6] = 0;
|
||||
r[7] = 0;
|
||||
r[8] = 0;
|
||||
r[9] = 0;
|
||||
}
|
||||
|
||||
void curve25519_set_d(bignum25519 r){
|
||||
curve25519_copy(r, ge25519_ecd);
|
||||
}
|
||||
|
||||
void curve25519_set_2d(bignum25519 r){
|
||||
curve25519_copy(r, ge25519_ec2d);
|
||||
}
|
||||
|
||||
void curve25519_set_sqrtneg1(bignum25519 r){
|
||||
curve25519_copy(r, ge25519_sqrtneg1);
|
||||
}
|
||||
|
||||
int curve25519_isnegative(const bignum25519 f) {
|
||||
unsigned char s[32];
|
||||
curve25519_contract(s, f);
|
||||
return s[0] & 1;
|
||||
}
|
||||
|
||||
int curve25519_isnonzero(const bignum25519 f) {
|
||||
unsigned char s[32];
|
||||
curve25519_contract(s, f);
|
||||
return ((((int) (s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7] | s[8] |
|
||||
s[9] | s[10] | s[11] | s[12] | s[13] | s[14] | s[15] | s[16] | s[17] |
|
||||
s[18] | s[19] | s[20] | s[21] | s[22] | s[23] | s[24] | s[25] | s[26] |
|
||||
s[27] | s[28] | s[29] | s[30] | s[31]) - 1) >> 8) + 1) & 0x1;
|
||||
}
|
||||
|
||||
void curve25519_reduce(bignum25519 out, const bignum25519 in) {
|
||||
uint32_t c;
|
||||
out[0] = in[0] ; c = (out[0] >> 26); out[0] &= reduce_mask_26;
|
||||
out[1] = in[1] + c; c = (out[1] >> 25); out[1] &= reduce_mask_25;
|
||||
out[2] = in[2] + c; c = (out[2] >> 26); out[2] &= reduce_mask_26;
|
||||
out[3] = in[3] + c; c = (out[3] >> 25); out[3] &= reduce_mask_25;
|
||||
out[4] = in[4] + c; c = (out[4] >> 26); out[4] &= reduce_mask_26;
|
||||
out[5] = in[5] + c; c = (out[5] >> 25); out[5] &= reduce_mask_25;
|
||||
out[6] = in[6] + c; c = (out[6] >> 26); out[6] &= reduce_mask_26;
|
||||
out[7] = in[7] + c; c = (out[7] >> 25); out[7] &= reduce_mask_25;
|
||||
out[8] = in[8] + c; c = (out[8] >> 26); out[8] &= reduce_mask_26;
|
||||
out[9] = in[9] + c; c = (out[9] >> 25); out[9] &= reduce_mask_25;
|
||||
out[0] += 19 * c;
|
||||
}
|
||||
|
||||
static void curve25519_divpowm1(bignum25519 r, const bignum25519 u, const bignum25519 v) {
|
||||
bignum25519 v3={0}, uv7={0}, t0={0}, t1={0}, t2={0};
|
||||
int i;
|
||||
|
||||
curve25519_square(v3, v);
|
||||
curve25519_mul(v3, v3, v); /* v3 = v^3 */
|
||||
curve25519_square(uv7, v3);
|
||||
curve25519_mul(uv7, uv7, v);
|
||||
curve25519_mul(uv7, uv7, u); /* uv7 = uv^7 */
|
||||
|
||||
/*fe_pow22523(uv7, uv7);*/
|
||||
/* From fe_pow22523.c */
|
||||
|
||||
curve25519_square(t0, uv7);
|
||||
curve25519_square(t1, t0);
|
||||
curve25519_square(t1, t1);
|
||||
curve25519_mul(t1, uv7, t1);
|
||||
curve25519_mul(t0, t0, t1);
|
||||
curve25519_square(t0, t0);
|
||||
curve25519_mul(t0, t1, t0);
|
||||
curve25519_square(t1, t0);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t0, t1, t0);
|
||||
curve25519_square(t1, t0);
|
||||
for (i = 0; i < 9; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t1, t1, t0);
|
||||
curve25519_square(t2, t1);
|
||||
for (i = 0; i < 19; ++i) {
|
||||
curve25519_square(t2, t2);
|
||||
}
|
||||
curve25519_mul(t1, t2, t1);
|
||||
for (i = 0; i < 10; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t0, t1, t0);
|
||||
curve25519_square(t1, t0);
|
||||
for (i = 0; i < 49; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t1, t1, t0);
|
||||
curve25519_square(t2, t1);
|
||||
for (i = 0; i < 99; ++i) {
|
||||
curve25519_square(t2, t2);
|
||||
}
|
||||
curve25519_mul(t1, t2, t1);
|
||||
for (i = 0; i < 50; ++i) {
|
||||
curve25519_square(t1, t1);
|
||||
}
|
||||
curve25519_mul(t0, t1, t0);
|
||||
curve25519_square(t0, t0);
|
||||
curve25519_square(t0, t0);
|
||||
curve25519_mul(t0, t0, uv7);
|
||||
|
||||
/* End fe_pow22523.c */
|
||||
/* t0 = (uv^7)^((q-5)/8) */
|
||||
curve25519_mul(t0, t0, v3);
|
||||
curve25519_mul(r, t0, u); /* u^(m+1)v^(-(m+1)) */
|
||||
}
|
||||
|
||||
void curve25519_expand_reduce(bignum25519 out, const unsigned char in[32]) {
|
||||
uint32_t x0,x1,x2,x3,x4,x5,x6,x7;
|
||||
#define F(s) \
|
||||
((((uint32_t)in[s + 0]) ) | \
|
||||
(((uint32_t)in[s + 1]) << 8) | \
|
||||
(((uint32_t)in[s + 2]) << 16) | \
|
||||
(((uint32_t)in[s + 3]) << 24))
|
||||
x0 = F(0);
|
||||
x1 = F(4);
|
||||
x2 = F(8);
|
||||
x3 = F(12);
|
||||
x4 = F(16);
|
||||
x5 = F(20);
|
||||
x6 = F(24);
|
||||
x7 = F(28);
|
||||
#undef F
|
||||
|
||||
out[0] = ( x0 ) & reduce_mask_26;
|
||||
out[1] = ((((uint64_t)x1 << 32) | x0) >> 26) & reduce_mask_25;
|
||||
out[2] = ((((uint64_t)x2 << 32) | x1) >> 19) & reduce_mask_26;
|
||||
out[3] = ((((uint64_t)x3 << 32) | x2) >> 13) & reduce_mask_25;
|
||||
out[4] = (( x3) >> 6) & reduce_mask_26;
|
||||
out[5] = ( x4 ) & reduce_mask_25;
|
||||
out[6] = ((((uint64_t)x5 << 32) | x4) >> 25) & reduce_mask_26;
|
||||
out[7] = ((((uint64_t)x6 << 32) | x5) >> 19) & reduce_mask_25;
|
||||
out[8] = ((((uint64_t)x7 << 32) | x6) >> 12) & reduce_mask_26;
|
||||
out[9] = (( x7) >> 6); // & reduce_mask_25; /* ignore the top bit */
|
||||
out[0] += 19 * (out[9] >> 25);
|
||||
out[9] &= reduce_mask_25;
|
||||
}
|
||||
|
||||
int ge25519_check(const ge25519 *r){
|
||||
/* return (z % q != 0 and
|
||||
x * y % q == z * t % q and
|
||||
(y * y - x * x - z * z - ed25519.d * t * t) % q == 0)
|
||||
*/
|
||||
|
||||
bignum25519 z={0}, lhs={0}, rhs={0}, tmp={0}, res={0};
|
||||
curve25519_reduce(z, r->z);
|
||||
|
||||
curve25519_mul(lhs, r->x, r->y);
|
||||
curve25519_mul(rhs, r->z, r->t);
|
||||
curve25519_sub_reduce(lhs, lhs, rhs);
|
||||
|
||||
curve25519_square(res, r->y);
|
||||
curve25519_square(tmp, r->x);
|
||||
curve25519_sub_reduce(res, res, tmp);
|
||||
curve25519_square(tmp, r->z);
|
||||
curve25519_sub_reduce(res, res, tmp);
|
||||
curve25519_square(tmp, r->t);
|
||||
curve25519_mul(tmp, tmp, ge25519_ecd);
|
||||
curve25519_sub_reduce(res, res, tmp);
|
||||
|
||||
const int c1 = curve25519_isnonzero(z);
|
||||
const int c2 = curve25519_isnonzero(lhs);
|
||||
const int c3 = curve25519_isnonzero(res);
|
||||
return c1 & (c2^0x1) & (c3^0x1);
|
||||
}
|
||||
|
||||
int ge25519_eq(const ge25519 *a, const ge25519 *b){
|
||||
int eq = 1;
|
||||
bignum25519 t1={0}, t2={0};
|
||||
|
||||
eq &= ge25519_check(a);
|
||||
eq &= ge25519_check(b);
|
||||
|
||||
curve25519_mul(t1, a->x, b->z);
|
||||
curve25519_mul(t2, b->x, a->z);
|
||||
curve25519_sub_reduce(t1, t1, t2);
|
||||
eq &= curve25519_isnonzero(t1) ^ 1;
|
||||
|
||||
curve25519_mul(t1, a->y, b->z);
|
||||
curve25519_mul(t2, b->y, a->z);
|
||||
curve25519_sub_reduce(t1, t1, t2);
|
||||
eq &= curve25519_isnonzero(t1) ^ 1;
|
||||
|
||||
return eq;
|
||||
}
|
||||
|
||||
void ge25519_copy(ge25519 *dst, const ge25519 *src){
|
||||
curve25519_copy(dst->x, src->x);
|
||||
curve25519_copy(dst->y, src->y);
|
||||
curve25519_copy(dst->z, src->z);
|
||||
curve25519_copy(dst->t, src->t);
|
||||
}
|
||||
|
||||
void ge25519_set_base(ge25519 *r){
|
||||
ge25519_copy(r, &ge25519_basepoint);
|
||||
}
|
||||
|
||||
void ge25519_mul8(ge25519 *r, const ge25519 *t) {
|
||||
ge25519_double_partial(r, t);
|
||||
ge25519_double_partial(r, r);
|
||||
ge25519_double(r, r);
|
||||
}
|
||||
|
||||
void ge25519_neg_partial(ge25519 *r){
|
||||
curve25519_neg(r->x, r->x);
|
||||
}
|
||||
|
||||
void ge25519_neg_full(ge25519 *r){
|
||||
curve25519_neg(r->x, r->x);
|
||||
curve25519_neg(r->t, r->t);
|
||||
}
|
||||
|
||||
void ge25519_reduce(ge25519 *r, const ge25519 *t){
|
||||
curve25519_reduce(r->x, t->x);
|
||||
curve25519_reduce(r->y, t->y);
|
||||
curve25519_reduce(r->z, t->z);
|
||||
curve25519_reduce(r->t, t->t);
|
||||
}
|
||||
|
||||
void ge25519_norm(ge25519 *r, const ge25519 * t){
|
||||
bignum25519 zinv;
|
||||
curve25519_recip(zinv, t->z);
|
||||
curve25519_mul(r->x, t->x, zinv);
|
||||
curve25519_mul(r->y, t->y, zinv);
|
||||
curve25519_mul(r->t, r->x, r->y);
|
||||
curve25519_set(r->z, 1);
|
||||
}
|
||||
|
||||
void ge25519_add(ge25519 *r, const ge25519 *p, const ge25519 *q, unsigned char signbit) {
|
||||
ge25519_pniels P_ni;
|
||||
ge25519_p1p1 P_11;
|
||||
|
||||
ge25519_full_to_pniels(&P_ni, q);
|
||||
ge25519_pnielsadd_p1p1(&P_11, p, &P_ni, signbit);
|
||||
ge25519_p1p1_to_full(r, &P_11);
|
||||
}
|
||||
|
||||
void ge25519_fromfe_frombytes_vartime(ge25519 *r, const unsigned char *s){
|
||||
bignum25519 u={0}, v={0}, w={0}, x={0}, y={0}, z={0};
|
||||
unsigned char sign;
|
||||
|
||||
curve25519_expand_reduce(u, s);
|
||||
|
||||
curve25519_square(v, u);
|
||||
curve25519_add_reduce(v, v, v); /* 2 * u^2 */
|
||||
curve25519_set(w, 1);
|
||||
curve25519_add_reduce(w, v, w); /* w = 2 * u^2 + 1 */
|
||||
|
||||
curve25519_square(x, w); /* w^2 */
|
||||
curve25519_mul(y, fe_ma2, v); /* -2 * A^2 * u^2 */
|
||||
curve25519_add_reduce(x, x, y); /* x = w^2 - 2 * A^2 * u^2 */
|
||||
|
||||
curve25519_divpowm1(r->x, w, x); /* (w / x)^(m + 1) */
|
||||
curve25519_square(y, r->x);
|
||||
curve25519_mul(x, y, x);
|
||||
curve25519_sub_reduce(y, w, x);
|
||||
curve25519_copy(z, fe_ma);
|
||||
|
||||
if (curve25519_isnonzero(y)) {
|
||||
curve25519_add_reduce(y, w, x);
|
||||
if (curve25519_isnonzero(y)) {
|
||||
goto negative;
|
||||
} else {
|
||||
curve25519_mul(r->x, r->x, fe_fffb1);
|
||||
}
|
||||
} else {
|
||||
curve25519_mul(r->x, r->x, fe_fffb2);
|
||||
}
|
||||
curve25519_mul(r->x, r->x, u); /* u * sqrt(2 * A * (A + 2) * w / x) */
|
||||
curve25519_mul(z, z, v); /* -2 * A * u^2 */
|
||||
sign = 0;
|
||||
goto setsign;
|
||||
negative:
|
||||
curve25519_mul(x, x, fe_sqrtm1);
|
||||
curve25519_sub_reduce(y, w, x);
|
||||
if (curve25519_isnonzero(y)) {
|
||||
assert((curve25519_add_reduce(y, w, x), !curve25519_isnonzero(y)));
|
||||
curve25519_mul(r->x, r->x, fe_fffb3);
|
||||
} else {
|
||||
curve25519_mul(r->x, r->x, fe_fffb4);
|
||||
}
|
||||
/* r->x = sqrt(A * (A + 2) * w / x) */
|
||||
/* z = -A */
|
||||
sign = 1;
|
||||
setsign:
|
||||
if (curve25519_isnegative(r->x) != sign) {
|
||||
assert(curve25519_isnonzero(r->x));
|
||||
curve25519_neg(r->x, r->x);
|
||||
}
|
||||
curve25519_add_reduce(r->z, z, w);
|
||||
curve25519_sub_reduce(r->y, z, w);
|
||||
curve25519_mul(r->x, r->x, r->z);
|
||||
|
||||
// Partial form, saving from T coord computation .
|
||||
// Later is mul8 discarding T anyway.
|
||||
// rt = ((rx * ry % q) * inv(rz)) % q
|
||||
// curve25519_mul(x, r->x, r->y);
|
||||
// curve25519_recip(z, r->z);
|
||||
// curve25519_mul(r->t, x, z);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
{
|
||||
bignum25519 check_x={0}, check_y={0}, check_iz={0}, check_v={0};
|
||||
curve25519_recip(check_iz, r->z);
|
||||
curve25519_mul(check_x, r->x, check_iz);
|
||||
curve25519_mul(check_y, r->y, check_iz);
|
||||
curve25519_square(check_x, check_x);
|
||||
curve25519_square(check_y, check_y);
|
||||
curve25519_mul(check_v, check_x, check_y);
|
||||
curve25519_mul(check_v, fe_d, check_v);
|
||||
curve25519_add_reduce(check_v, check_v, check_x);
|
||||
curve25519_sub_reduce(check_v, check_v, check_y);
|
||||
curve25519_set(check_x, 1);
|
||||
curve25519_add_reduce(check_v, check_v, check_x);
|
||||
assert(!curve25519_isnonzero(check_v));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int ge25519_unpack_vartime(ge25519 *r, const unsigned char *s){
|
||||
int res = ge25519_unpack_negative_vartime(r, s);
|
||||
ge25519_neg_full(r);
|
||||
return res;
|
||||
}
|
||||
|
||||
void ge25519_scalarmult_base_wrapper(ge25519 *r, const bignum256modm s){
|
||||
ge25519_scalarmult_base_niels(r, ge25519_niels_base_multiples, s);
|
||||
ge25519_norm(r, r);
|
||||
}
|
||||
|
||||
void ge25519_scalarmult_wrapper(ge25519 *r, const ge25519 *P, const bignum256modm a){
|
||||
ge25519_scalarmult(r, P, a);
|
||||
ge25519_norm(r, r);
|
||||
}
|
77
ed25519-donna/ge25519.h
Normal file
77
ed25519-donna/ge25519.h
Normal file
@ -0,0 +1,77 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 29/04/2018.
|
||||
//
|
||||
|
||||
#ifndef GE25519_H
|
||||
#define GE25519_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ed25519-donna.h"
|
||||
|
||||
/* uint32_t to Zmod(2^255-19) */
|
||||
void curve25519_set(bignum25519 r, uint32_t x);
|
||||
|
||||
/* set d */
|
||||
void curve25519_set_d(bignum25519 r);
|
||||
|
||||
/* set 2d */
|
||||
void curve25519_set_2d(bignum25519 r);
|
||||
|
||||
/* set sqrt(-1) */
|
||||
void curve25519_set_sqrtneg1(bignum25519 r);
|
||||
|
||||
/* constant time Zmod(2^255-19) negative test */
|
||||
int curve25519_isnegative(const bignum25519 f);
|
||||
|
||||
/* constant time Zmod(2^255-19) non-zero test */
|
||||
int curve25519_isnonzero(const bignum25519 f);
|
||||
|
||||
/* reduce Zmod(2^255-19) */
|
||||
void curve25519_reduce(bignum25519 r, const bignum25519 in);
|
||||
|
||||
/* Zmod(2^255-19) from byte array to bignum25519 expansion with modular reduction */
|
||||
void curve25519_expand_reduce(bignum25519 out, const unsigned char in[32]);
|
||||
|
||||
/* check if r is on curve */
|
||||
int ge25519_check(const ge25519 *r);
|
||||
|
||||
/* a == b */
|
||||
int ge25519_eq(const ge25519 *a, const ge25519 *b);
|
||||
|
||||
/* copies one point to another */
|
||||
void ge25519_copy(ge25519 *dst, const ge25519 *src);
|
||||
|
||||
/* sets B point to r */
|
||||
void ge25519_set_base(ge25519 *r);
|
||||
|
||||
/* 8*P */
|
||||
void ge25519_mul8(ge25519 *r, const ge25519 *t);
|
||||
|
||||
/* -P */
|
||||
void ge25519_neg_partial(ge25519 *r);
|
||||
|
||||
/* -P */
|
||||
void ge25519_neg_full(ge25519 *r);
|
||||
|
||||
/* reduce all coords */
|
||||
void ge25519_reduce(ge25519 *r, const ge25519 *t);
|
||||
|
||||
/* normalizes coords. (x, y, 1, x*y) */
|
||||
void ge25519_norm(ge25519 *r, const ge25519 * t);
|
||||
|
||||
/* Simple addition */
|
||||
void ge25519_add(ge25519 *r, const ge25519 *a, const ge25519 *b, unsigned char signbit);
|
||||
|
||||
/* point from bytes, used in H_p() */
|
||||
void ge25519_fromfe_frombytes_vartime(ge25519 *r, const unsigned char *s);
|
||||
|
||||
/* point from bytes */
|
||||
int ge25519_unpack_vartime(ge25519 *r, const unsigned char *s);
|
||||
|
||||
/* aG, wrapper for niels base mult. */
|
||||
void ge25519_scalarmult_base_wrapper(ge25519 *r, const bignum256modm s);
|
||||
|
||||
/* aP, wrapper. General purpose, normalizes after multiplication */
|
||||
void ge25519_scalarmult_wrapper(ge25519 *r, const ge25519 *P, const bignum256modm a);
|
||||
|
||||
#endif
|
@ -408,3 +408,110 @@ void contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set256_modm(bignum256modm r, uint64_t v) {
|
||||
r[0] = (bignum256modm_element_t) (v & 0x3fffffff); v >>= 30;
|
||||
r[1] = (bignum256modm_element_t) (v & 0x3fffffff); v >>= 30;
|
||||
r[2] = (bignum256modm_element_t) (v & 0x3fffffff);
|
||||
r[3] = 0;
|
||||
r[4] = 0;
|
||||
r[5] = 0;
|
||||
r[6] = 0;
|
||||
r[7] = 0;
|
||||
r[8] = 0;
|
||||
}
|
||||
|
||||
int get256_modm(uint64_t * v, const bignum256modm r){
|
||||
*v = 0;
|
||||
int con1 = 0;
|
||||
|
||||
#define NONZ(x) ((((((int64_t)(x)) - 1) >> 32) + 1) & 1)
|
||||
bignum256modm_element_t c = 0;
|
||||
c = r[0]; *v += (uint64_t)c & 0x3fffffff; c >>= 30; // 30
|
||||
c += r[1]; *v += ((uint64_t)c & 0x3fffffff) << 30; c >>= 30; // 60
|
||||
c += r[2]; *v += ((uint64_t)c & 0xf) << 60; con1 |= NONZ(c>>4); c >>= 30; // 64 bits
|
||||
c += r[3]; con1 |= NONZ(c); c >>= 30;
|
||||
c += r[4]; con1 |= NONZ(c); c >>= 30;
|
||||
c += r[5]; con1 |= NONZ(c); c >>= 30;
|
||||
c += r[6]; con1 |= NONZ(c); c >>= 30;
|
||||
c += r[7]; con1 |= NONZ(c); c >>= 30;
|
||||
c += r[8]; con1 |= NONZ(c); c >>= 30;
|
||||
con1 |= NONZ(c);
|
||||
#undef NONZ
|
||||
|
||||
return con1 ^ 1;
|
||||
}
|
||||
|
||||
int eq256_modm(const bignum256modm x, const bignum256modm y){
|
||||
size_t differentbits = 0;
|
||||
int len = bignum256modm_limb_size;
|
||||
while (len--) {
|
||||
differentbits |= (*x++ ^ *y++);
|
||||
}
|
||||
return (int) (1 & ((differentbits - 1) >> bignum256modm_bits_per_limb));
|
||||
}
|
||||
|
||||
int cmp256_modm(const bignum256modm x, const bignum256modm y){
|
||||
int len = 2*bignum256modm_limb_size;
|
||||
uint32_t a_gt = 0;
|
||||
uint32_t b_gt = 0;
|
||||
|
||||
// 16B chunks
|
||||
while (len--) {
|
||||
const uint32_t ln = (const uint32_t) len;
|
||||
const uint32_t a = (x[ln>>1] >> 16*(ln & 1)) & 0xffff;
|
||||
const uint32_t b = (y[ln>>1] >> 16*(ln & 1)) & 0xffff;
|
||||
|
||||
const uint32_t limb_a_gt = ((b - a) >> 16) & 1;
|
||||
const uint32_t limb_b_gt = ((a - b) >> 16) & 1;
|
||||
a_gt |= limb_a_gt & ~b_gt;
|
||||
b_gt |= limb_b_gt & ~a_gt;
|
||||
}
|
||||
|
||||
return a_gt - b_gt;
|
||||
}
|
||||
|
||||
int iszero256_modm(const bignum256modm x){
|
||||
size_t differentbits = 0;
|
||||
int len = bignum256modm_limb_size;
|
||||
while (len--) {
|
||||
differentbits |= (*x++);
|
||||
}
|
||||
return (int) (1 & ((differentbits - 1) >> bignum256modm_bits_per_limb));
|
||||
}
|
||||
|
||||
void copy256_modm(bignum256modm r, const bignum256modm x){
|
||||
r[0] = x[0];
|
||||
r[1] = x[1];
|
||||
r[2] = x[2];
|
||||
r[3] = x[3];
|
||||
r[4] = x[4];
|
||||
r[5] = x[5];
|
||||
r[6] = x[6];
|
||||
r[7] = x[7];
|
||||
r[8] = x[8];
|
||||
}
|
||||
|
||||
int check256_modm(const bignum256modm x){
|
||||
int ok = 1;
|
||||
bignum256modm t={0}, z={0};
|
||||
|
||||
ok &= iszero256_modm(x) ^ 1;
|
||||
barrett_reduce256_modm(t, z, x);
|
||||
ok &= eq256_modm(t, x);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void mulsub256_modm(bignum256modm r, const bignum256modm a, const bignum256modm b, const bignum256modm c){
|
||||
//(cc - aa * bb) % l
|
||||
bignum256modm t={0};
|
||||
mul256_modm(t, a, b);
|
||||
sub256_modm(r, c, t);
|
||||
}
|
||||
|
||||
void muladd256_modm(bignum256modm r, const bignum256modm a, const bignum256modm b, const bignum256modm c){
|
||||
//(cc + aa * bb) % l
|
||||
bignum256modm t={0};
|
||||
mul256_modm(t, a, b);
|
||||
add256_modm(r, c, t);
|
||||
}
|
||||
|
@ -51,3 +51,30 @@ void contract256_modm(unsigned char out[32], const bignum256modm in);
|
||||
void contract256_window4_modm(signed char r[64], const bignum256modm in);
|
||||
|
||||
void contract256_slidingwindow_modm(signed char r[256], const bignum256modm s, int windowsize);
|
||||
|
||||
/* 64bit uint to scalar value */
|
||||
void set256_modm(bignum256modm r, uint64_t v);
|
||||
|
||||
/* scalar value to 64bit uint */
|
||||
int get256_modm(uint64_t * v, const bignum256modm r);
|
||||
|
||||
/* equality test on two reduced scalar values */
|
||||
int eq256_modm(const bignum256modm x, const bignum256modm y);
|
||||
|
||||
/* comparison of two reduced scalar values */
|
||||
int cmp256_modm(const bignum256modm x, const bignum256modm y);
|
||||
|
||||
/* scalar null check, has to be reduced */
|
||||
int iszero256_modm(const bignum256modm x);
|
||||
|
||||
/* simple copy, no reduction */
|
||||
void copy256_modm(bignum256modm r, const bignum256modm x);
|
||||
|
||||
/* check if nonzero && same after reduction */
|
||||
int check256_modm(const bignum256modm x);
|
||||
|
||||
/* (cc - aa * bb) % l */
|
||||
void mulsub256_modm(bignum256modm r, const bignum256modm a, const bignum256modm b, const bignum256modm c);
|
||||
|
||||
/* (cc + aa * bb) % l */
|
||||
void muladd256_modm(bignum256modm r, const bignum256modm a, const bignum256modm b, const bignum256modm c);
|
||||
|
243
monero/base58.c
Normal file
243
monero/base58.c
Normal file
@ -0,0 +1,243 @@
|
||||
// Copyright (c) 2014-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include "base58.h"
|
||||
#include "int-util.h"
|
||||
#include "sha2.h"
|
||||
#include "../base58.h"
|
||||
|
||||
const size_t alphabet_size = 58; // sizeof(b58digits_ordered) - 1;
|
||||
const size_t encoded_block_sizes[] = {0, 2, 3, 5, 6, 7, 9, 10, 11};
|
||||
const size_t full_block_size = sizeof(encoded_block_sizes) / sizeof(encoded_block_sizes[0]) - 1;
|
||||
const size_t full_encoded_block_size = 11; // encoded_block_sizes[full_block_size];
|
||||
const size_t addr_checksum_size = 4;
|
||||
const int decoded_block_sizes[] = {0, -1, 1, 2, -1, 3, 4, 5, -1, 6, 7, 8};
|
||||
#define reverse_alphabet(letter) ((int8_t) b58digits_map[(int)letter])
|
||||
|
||||
|
||||
uint64_t uint_8be_to_64(const uint8_t* data, size_t size)
|
||||
{
|
||||
assert(1 <= size && size <= sizeof(uint64_t));
|
||||
|
||||
uint64_t res = 0;
|
||||
switch (9 - size)
|
||||
{
|
||||
case 1: res |= *data++; /* FALLTHRU */
|
||||
case 2: res <<= 8; res |= *data++; /* FALLTHRU */
|
||||
case 3: res <<= 8; res |= *data++; /* FALLTHRU */
|
||||
case 4: res <<= 8; res |= *data++; /* FALLTHRU */
|
||||
case 5: res <<= 8; res |= *data++; /* FALLTHRU */
|
||||
case 6: res <<= 8; res |= *data++; /* FALLTHRU */
|
||||
case 7: res <<= 8; res |= *data++; /* FALLTHRU */
|
||||
case 8: res <<= 8; res |= *data; break;
|
||||
default: assert(false);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void uint_64_to_8be(uint64_t num, size_t size, uint8_t* data)
|
||||
{
|
||||
assert(1 <= size && size <= sizeof(uint64_t));
|
||||
|
||||
uint64_t num_be = SWAP64(num);
|
||||
memcpy(data, (uint8_t*)(&num_be) + sizeof(uint64_t) - size, size);
|
||||
}
|
||||
|
||||
void encode_block(const char* block, size_t size, char* res)
|
||||
{
|
||||
assert(1 <= size && size <= full_block_size);
|
||||
|
||||
uint64_t num = uint_8be_to_64((uint8_t*)(block), size);
|
||||
int i = ((int)(encoded_block_sizes[size])) - 1;
|
||||
while (0 <= i)
|
||||
{
|
||||
uint64_t remainder = num % alphabet_size;
|
||||
num /= alphabet_size;
|
||||
res[i] = b58digits_ordered[remainder];
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
bool decode_block(const char* block, size_t size, char* res)
|
||||
{
|
||||
assert(1 <= size && size <= full_encoded_block_size);
|
||||
|
||||
int res_size = decoded_block_sizes[size];
|
||||
if (res_size <= 0)
|
||||
return false; // Invalid block size
|
||||
|
||||
uint64_t res_num = 0;
|
||||
uint64_t order = 1;
|
||||
for (size_t i = size - 1; i < size; --i)
|
||||
{
|
||||
int digit = reverse_alphabet(block[i]);
|
||||
if (digit < 0)
|
||||
return false; // Invalid symbol
|
||||
|
||||
uint64_t product_hi;
|
||||
uint64_t tmp = res_num + mul128(order, (uint64_t) digit, &product_hi);
|
||||
if (tmp < res_num || 0 != product_hi)
|
||||
return false; // Overflow
|
||||
|
||||
res_num = tmp;
|
||||
order *= alphabet_size; // Never overflows, 58^10 < 2^64
|
||||
}
|
||||
|
||||
if ((size_t)res_size < full_block_size && (UINT64_C(1) << (8 * res_size)) <= res_num)
|
||||
return false; // Overflow
|
||||
|
||||
uint_64_to_8be(res_num, res_size, (uint8_t*)(res));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool xmr_base58_encode(char *b58, size_t *b58sz, const void *data, size_t binsz)
|
||||
{
|
||||
if (binsz==0)
|
||||
return true;
|
||||
|
||||
const char * data_bin = data;
|
||||
size_t full_block_count = binsz / full_block_size;
|
||||
size_t last_block_size = binsz % full_block_size;
|
||||
size_t res_size = full_block_count * full_encoded_block_size + encoded_block_sizes[last_block_size];
|
||||
|
||||
if (b58sz){
|
||||
if (res_size >= *b58sz){
|
||||
return false;
|
||||
}
|
||||
*b58sz = res_size;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < full_block_count; ++i)
|
||||
{
|
||||
encode_block(data_bin + i * full_block_size, full_block_size, b58 + i * full_encoded_block_size);
|
||||
}
|
||||
|
||||
if (0 < last_block_size)
|
||||
{
|
||||
encode_block(data_bin + full_block_count * full_block_size, last_block_size, b58 + full_block_count * full_encoded_block_size);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool xmr_base58_decode(const char *b58, size_t b58sz, void *data, size_t *binsz)
|
||||
{
|
||||
if (b58sz == 0) {
|
||||
*binsz = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t full_block_count = b58sz / full_encoded_block_size;
|
||||
size_t last_block_size = b58sz % full_encoded_block_size;
|
||||
int last_block_decoded_size = decoded_block_sizes[last_block_size];
|
||||
if (last_block_decoded_size < 0) {
|
||||
*binsz = 0;
|
||||
return false; // Invalid enc length
|
||||
}
|
||||
|
||||
size_t data_size = full_block_count * full_block_size + last_block_decoded_size;
|
||||
if (*binsz < data_size){
|
||||
*binsz = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
char * data_bin = data;
|
||||
for (size_t i = 0; i < full_block_count; ++i)
|
||||
{
|
||||
if (!decode_block(b58 + i * full_encoded_block_size, full_encoded_block_size, data_bin + i * full_block_size))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (0 < last_block_size)
|
||||
{
|
||||
if (!decode_block(b58 + full_block_count * full_encoded_block_size, last_block_size,
|
||||
data_bin + full_block_count * full_block_size))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int xmr_base58_addr_encode_check(uint64_t tag, const uint8_t *data, size_t binsz, char *b58, size_t b58sz)
|
||||
{
|
||||
if (binsz > 128 || tag > 127) { // tag varint
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t b58size = b58sz;
|
||||
uint8_t buf[binsz + 1 + HASHER_DIGEST_LENGTH];
|
||||
uint8_t *hash = buf + binsz + 1;
|
||||
buf[0] = (uint8_t) tag;
|
||||
memcpy(buf + 1, data, binsz);
|
||||
hasher_Raw(HASHER_SHA3K, buf, binsz + 1, hash);
|
||||
|
||||
bool r = xmr_base58_encode(b58, &b58size, buf, binsz + 1 + addr_checksum_size);
|
||||
return (int) (!r ? 0 : b58size);
|
||||
}
|
||||
|
||||
int xmr_base58_addr_decode_check(const char *addr, size_t sz, uint64_t *tag, void *data, size_t datalen)
|
||||
{
|
||||
size_t buflen = 1 + 64 + addr_checksum_size;
|
||||
uint8_t buf[buflen];
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH];
|
||||
|
||||
if (!xmr_base58_decode(addr, sz, buf, &buflen)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t res_size = buflen - addr_checksum_size - 1;
|
||||
if (datalen < res_size){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (buflen <= addr_checksum_size+1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
hasher_Raw(HASHER_SHA3K, buf, buflen - addr_checksum_size, hash);
|
||||
if (memcmp(hash, buf + buflen - addr_checksum_size, addr_checksum_size) != 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
*tag = buf[0];
|
||||
if (*tag > 127){
|
||||
return false; // varint
|
||||
}
|
||||
|
||||
memcpy(data, buf+1, res_size);
|
||||
return (int) res_size;
|
||||
}
|
43
monero/base58.h
Normal file
43
monero/base58.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2014-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#ifndef __XMR_BASE58_H__
|
||||
#define __XMR_BASE58_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "hasher.h"
|
||||
#include "options.h"
|
||||
|
||||
int xmr_base58_addr_encode_check(uint64_t tag, const uint8_t *data, size_t binsz, char *b58, size_t b58sz);
|
||||
int xmr_base58_addr_decode_check(const char *addr, size_t sz, uint64_t *tag, void *data, size_t datalen);
|
||||
bool xmr_base58_encode(char *b58, size_t *b58sz, const void *data, size_t binsz);
|
||||
bool xmr_base58_decode(const char *b58, size_t b58sz, void *data, size_t *binsz);
|
||||
|
||||
#endif
|
77
monero/int-util.h
Normal file
77
monero/int-util.h
Normal file
@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2014-2018, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static inline uint64_t hi_dword(uint64_t val) {
|
||||
return val >> 32;
|
||||
}
|
||||
|
||||
static inline uint64_t lo_dword(uint64_t val) {
|
||||
return val & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) {
|
||||
// multiplier = ab = a * 2^32 + b
|
||||
// multiplicand = cd = c * 2^32 + d
|
||||
// ab * cd = a * c * 2^64 + (a * d + b * c) * 2^32 + b * d
|
||||
uint64_t a = hi_dword(multiplier);
|
||||
uint64_t b = lo_dword(multiplier);
|
||||
uint64_t c = hi_dword(multiplicand);
|
||||
uint64_t d = lo_dword(multiplicand);
|
||||
|
||||
uint64_t ac = a * c;
|
||||
uint64_t ad = a * d;
|
||||
uint64_t bc = b * c;
|
||||
uint64_t bd = b * d;
|
||||
|
||||
uint64_t adbc = ad + bc;
|
||||
uint64_t adbc_carry = adbc < ad ? 1 : 0;
|
||||
|
||||
// multiplier * multiplicand = product_hi * 2^64 + product_lo
|
||||
uint64_t product_lo = bd + (adbc << 32);
|
||||
uint64_t product_lo_carry = product_lo < bd ? 1 : 0;
|
||||
*product_hi = ac + (adbc >> 32) + (adbc_carry << 32) + product_lo_carry;
|
||||
assert(ac <= *product_hi);
|
||||
|
||||
return product_lo;
|
||||
}
|
||||
|
||||
#define SWAP64(x) ((((uint64_t) (x) & 0x00000000000000ff) << 56) | \
|
||||
(((uint64_t) (x) & 0x000000000000ff00) << 40) | \
|
||||
(((uint64_t) (x) & 0x0000000000ff0000) << 24) | \
|
||||
(((uint64_t) (x) & 0x00000000ff000000) << 8) | \
|
||||
(((uint64_t) (x) & 0x000000ff00000000) >> 8) | \
|
||||
(((uint64_t) (x) & 0x0000ff0000000000) >> 24) | \
|
||||
(((uint64_t) (x) & 0x00ff000000000000) >> 40) | \
|
||||
(((uint64_t) (x) & 0xff00000000000000) >> 56))
|
21
monero/monero.h
Normal file
21
monero/monero.h
Normal file
@ -0,0 +1,21 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 10/05/2018.
|
||||
//
|
||||
|
||||
#ifndef TREZOR_CRYPTO_MONERO_H
|
||||
#define TREZOR_CRYPTO_MONERO_H
|
||||
|
||||
#if !USE_MONERO
|
||||
#error "Compile with -DUSE_MONERO=1"
|
||||
#endif
|
||||
|
||||
#if !USE_KECCAK
|
||||
#error "Compile with -DUSE_KECCAK=1"
|
||||
#endif
|
||||
|
||||
#include "base58.h"
|
||||
#include "serialize.h"
|
||||
#include "xmr.h"
|
||||
#include "range_proof.h"
|
||||
|
||||
#endif //TREZOR_CRYPTO_MONERO_H
|
115
monero/range_proof.c
Normal file
115
monero/range_proof.c
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 10/05/2018.
|
||||
//
|
||||
|
||||
#include "range_proof.h"
|
||||
|
||||
|
||||
static void xmr_hash_ge25519_to_scalar(bignum256modm r, const ge25519 *p){
|
||||
unsigned char buff[32];
|
||||
ge25519_pack(buff, p);
|
||||
xmr_hash_to_scalar(r, buff, sizeof(buff));
|
||||
}
|
||||
|
||||
void xmr_gen_range_sig(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask){
|
||||
bignum256modm ai[64];
|
||||
bignum256modm alpha[64];
|
||||
xmr_gen_range_sig_ex(sig, C, mask, amount, last_mask, ai, alpha);
|
||||
}
|
||||
|
||||
void xmr_gen_range_sig_ex(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask,
|
||||
bignum256modm ai[64], bignum256modm alpha[64])
|
||||
{
|
||||
const unsigned n = XMR_ATOMS;
|
||||
bignum256modm a={0};
|
||||
bignum256modm si={0};
|
||||
bignum256modm c={0};
|
||||
bignum256modm ee={0};
|
||||
unsigned char buff[32];
|
||||
|
||||
Hasher kck;
|
||||
xmr_hasher_init(&kck);
|
||||
|
||||
ge25519 C_acc;
|
||||
ge25519 C_h;
|
||||
ge25519 C_tmp;
|
||||
ge25519 L;
|
||||
ge25519 Zero;
|
||||
|
||||
ge25519_set_neutral(&Zero);
|
||||
ge25519_set_neutral(&C_acc);
|
||||
ge25519_set_xmr_h(&C_h);
|
||||
set256_modm(a, 0);
|
||||
|
||||
#define BB(i) ((amount>>(i)) & 1)
|
||||
|
||||
// First pass, generates: ai, alpha, Ci, ee, s1
|
||||
for(unsigned ii=0; ii<n; ++ii){
|
||||
xmr_random_scalar(ai[ii]);
|
||||
if (last_mask != NULL && ii == n - 1){
|
||||
sub256_modm(ai[ii], *last_mask, a);
|
||||
}
|
||||
|
||||
add256_modm(a, a, ai[ii]); // creating the total mask since you have to pass this to receiver...
|
||||
xmr_random_scalar(alpha[ii]);
|
||||
|
||||
ge25519_scalarmult_base_niels(&L, ge25519_niels_base_multiples, alpha[ii]);
|
||||
ge25519_scalarmult_base_niels(&C_tmp, ge25519_niels_base_multiples, ai[ii]);
|
||||
|
||||
// C_tmp += &Zero if BB(ii) == 0 else &C_h
|
||||
ge25519_add(&C_tmp, &C_tmp, BB(ii) == 0 ? &Zero : &C_h, 0);
|
||||
ge25519_add(&C_acc, &C_acc, &C_tmp, 0);
|
||||
|
||||
// Set Ci[ii] to sigs
|
||||
ge25519_pack(sig->Ci[ii], &C_tmp);
|
||||
|
||||
if (BB(ii) == 0) {
|
||||
xmr_random_scalar(si);
|
||||
xmr_hash_ge25519_to_scalar(c, &L);
|
||||
|
||||
ge25519_add(&C_tmp, &C_tmp, &C_h, 1); // Ci[ii] -= c_h
|
||||
xmr_add_keys2_vartime(&L, si, c, &C_tmp);
|
||||
|
||||
// Set s1[ii] to sigs
|
||||
contract256_modm(sig->asig.s1[ii], si);
|
||||
}
|
||||
|
||||
ge25519_pack(buff, &L);
|
||||
xmr_hasher_update(&kck, buff, sizeof(buff));
|
||||
|
||||
ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2)
|
||||
}
|
||||
|
||||
// Compute ee
|
||||
xmr_hasher_final(&kck, buff);
|
||||
expand256_modm(ee, buff, sizeof(buff));
|
||||
|
||||
ge25519_set_xmr_h(&C_h);
|
||||
|
||||
// Second pass, s0, s1
|
||||
for(unsigned ii=0; ii<n; ++ii){
|
||||
if (BB(ii) == 0){
|
||||
mulsub256_modm(si, ai[ii], ee, alpha[ii]);
|
||||
contract256_modm(sig->asig.s0[ii], si);
|
||||
|
||||
} else {
|
||||
xmr_random_scalar(si);
|
||||
contract256_modm(sig->asig.s0[ii], si);
|
||||
|
||||
ge25519_unpack_vartime(&C_tmp, sig->Ci[ii]);
|
||||
xmr_add_keys2_vartime(&L, si, ee, &C_tmp);
|
||||
xmr_hash_ge25519_to_scalar(c, &L);
|
||||
|
||||
mulsub256_modm(si, ai[ii], c, alpha[ii]);
|
||||
contract256_modm(sig->asig.s1[ii], si);
|
||||
}
|
||||
|
||||
ge25519_double(&C_h, &C_h); // c_H = crypto.scalarmult(c_H, 2)
|
||||
}
|
||||
|
||||
ge25519_copy(C, &C_acc);
|
||||
copy256_modm(mask, a);
|
||||
contract256_modm(sig->asig.ee, ee);
|
||||
#undef BB
|
||||
}
|
||||
|
30
monero/range_proof.h
Normal file
30
monero/range_proof.h
Normal file
@ -0,0 +1,30 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 10/05/2018.
|
||||
//
|
||||
|
||||
#ifndef TREZOR_CRYPTO_RANGE_PROOF_H
|
||||
#define TREZOR_CRYPTO_RANGE_PROOF_H
|
||||
|
||||
#include "xmr.h"
|
||||
#define XMR_ATOMS 64
|
||||
|
||||
typedef uint64_t xmr_amount;
|
||||
typedef xmr_key_t xmr_key64_t[64];
|
||||
|
||||
typedef struct xmr_boro_sig {
|
||||
xmr_key64_t s0;
|
||||
xmr_key64_t s1;
|
||||
xmr_key_t ee;
|
||||
} xmr_boro_sig_t;
|
||||
|
||||
typedef struct range_sig {
|
||||
xmr_boro_sig_t asig;
|
||||
xmr_key64_t Ci;
|
||||
} xmr_range_sig_t;
|
||||
|
||||
|
||||
void xmr_gen_range_sig(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask);
|
||||
void xmr_gen_range_sig_ex(xmr_range_sig_t * sig, ge25519 * C, bignum256modm mask, xmr_amount amount, bignum256modm * last_mask,
|
||||
bignum256modm ai[64], bignum256modm alpha[64]);
|
||||
|
||||
#endif //TREZOR_CRYPTO_RANGE_PROOF_H
|
54
monero/serialize.c
Normal file
54
monero/serialize.c
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 02/05/2018.
|
||||
//
|
||||
|
||||
#include "serialize.h"
|
||||
|
||||
int xmr_size_varint(uint64_t num){
|
||||
int ctr = 1;
|
||||
while (num >= 0x80) {
|
||||
++ctr;
|
||||
num >>= 7;
|
||||
}
|
||||
return ctr;
|
||||
}
|
||||
|
||||
int xmr_write_varint(uint8_t * buff, size_t buff_size, uint64_t num){
|
||||
unsigned ctr = 0;
|
||||
while (num >= 0x80 && ctr < buff_size) {
|
||||
*buff = (uint8_t) (((num) & 0x7f) | 0x80);
|
||||
++buff;
|
||||
++ctr;
|
||||
num >>= 7;
|
||||
}
|
||||
|
||||
/* writes the last one to dest */
|
||||
if (ctr < buff_size) {
|
||||
*buff = (uint8_t) num;
|
||||
++ctr;
|
||||
}
|
||||
return ctr <= buff_size ? (int)ctr : -1;
|
||||
}
|
||||
|
||||
int xmr_read_varint(uint8_t * buff, size_t buff_size, uint64_t *val) {
|
||||
unsigned read = 0;
|
||||
int finished_ok = 0;
|
||||
*val = 0;
|
||||
|
||||
for (int shift = 0; read < buff_size; shift += 7, ++read) {
|
||||
uint8_t byte = buff[read];
|
||||
if (byte == 0 && shift != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*val |= (uint64_t)(byte & 0x7f) << shift;
|
||||
|
||||
/* If there is no next */
|
||||
if ((byte & 0x80) == 0) {
|
||||
finished_ok = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return finished_ok ? (int)read + 1 : -2;
|
||||
}
|
||||
|
15
monero/serialize.h
Normal file
15
monero/serialize.h
Normal file
@ -0,0 +1,15 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 02/05/2018.
|
||||
//
|
||||
|
||||
#ifndef TREZOR_XMR_SERIALIZE_H
|
||||
#define TREZOR_XMR_SERIALIZE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int xmr_size_varint(uint64_t num);
|
||||
int xmr_write_varint(uint8_t * buff, size_t buff_size, uint64_t num);
|
||||
int xmr_read_varint(uint8_t * buff, size_t buff_size, uint64_t *val);
|
||||
|
||||
#endif //TREZOR_XMR_SERIALIZE_H
|
159
monero/xmr.c
Normal file
159
monero/xmr.c
Normal file
@ -0,0 +1,159 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 10/05/2018.
|
||||
//
|
||||
|
||||
#include "xmr.h"
|
||||
#include "int-util.h"
|
||||
#include "serialize.h"
|
||||
#include "rand.h"
|
||||
|
||||
|
||||
const ge25519 ALIGN(16) xmr_h = {
|
||||
{0x1861ec7, 0x1ceac77, 0x2f11626, 0x1f261d3, 0x346107c, 0x06d8c4a, 0x254201d, 0x1675c09, 0x1301c3f, 0x0211d73},
|
||||
{0x326feb4, 0x12e30cc, 0x0cf54b4, 0x1117305, 0x318f5d5, 0x06cf754, 0x2e578a1, 0x1daf058, 0x34430a1, 0x04410e9},
|
||||
{0x0fde4d2, 0x0774049, 0x22ca951, 0x05aec2b, 0x07a36a5, 0x1394f13, 0x3c5385c, 0x1adb924, 0x2b6c581, 0x0a55fa4},
|
||||
{0x24517f7, 0x05ee936, 0x3acf5d9, 0x14b08aa, 0x3363738, 0x1051745, 0x360601e, 0x0f3f2c9, 0x1ead2cd, 0x1d3e3df}
|
||||
};
|
||||
|
||||
|
||||
void ge25519_set_xmr_h(ge25519 *r){
|
||||
ge25519_copy(r, &xmr_h);
|
||||
}
|
||||
|
||||
void xmr_random_scalar(bignum256modm m){
|
||||
unsigned char buff[32]={0};
|
||||
random_buffer(buff, sizeof(buff));
|
||||
expand256_modm(m, buff, sizeof(buff));
|
||||
}
|
||||
|
||||
void xmr_fast_hash(uint8_t * hash, const void *data, size_t length){
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
}
|
||||
|
||||
void xmr_hasher_init(Hasher * hasher){
|
||||
hasher_Init(hasher, HASHER_SHA3K);
|
||||
}
|
||||
|
||||
void xmr_hasher_update(Hasher * hasher, const void *data, size_t length){
|
||||
hasher_Update(hasher, data, length);
|
||||
}
|
||||
|
||||
void xmr_hasher_final(Hasher * hasher, uint8_t * hash){
|
||||
hasher_Final(hasher, hash);
|
||||
}
|
||||
|
||||
void xmr_hasher_copy(Hasher * dst, const Hasher * src){
|
||||
memcpy(dst, src, sizeof(Hasher));
|
||||
}
|
||||
|
||||
void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length){
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH];
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
expand256_modm(r, hash, HASHER_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
void xmr_hash_to_ec(ge25519 *P, const void *data, size_t length){
|
||||
ge25519 point2;
|
||||
uint8_t hash[HASHER_DIGEST_LENGTH];
|
||||
hasher_Raw(HASHER_SHA3K, data, length, hash);
|
||||
|
||||
ge25519_fromfe_frombytes_vartime(&point2, hash);
|
||||
ge25519_mul8(P, &point2);
|
||||
}
|
||||
|
||||
void xmr_derivation_to_scalar(bignum256modm s, const ge25519 * p, uint32_t output_index){
|
||||
uint8_t buff[32 + 8];
|
||||
ge25519_pack(buff, p);
|
||||
int written = xmr_write_varint(buff + 32, 8, output_index);
|
||||
xmr_hash_to_scalar(s, buff, 32u + written);
|
||||
}
|
||||
|
||||
void xmr_generate_key_derivation(ge25519 * r, const ge25519 * A, const bignum256modm b){
|
||||
ge25519 bA;
|
||||
ge25519_scalarmult(&bA, A, b);
|
||||
ge25519_norm(&bA, &bA);
|
||||
ge25519_mul8(r, &bA);
|
||||
}
|
||||
|
||||
void xmr_derive_private_key(bignum256modm s, const ge25519 * deriv, uint32_t idx, const bignum256modm base){
|
||||
xmr_derivation_to_scalar(s, deriv, idx);
|
||||
add256_modm(s, s, base);
|
||||
}
|
||||
|
||||
void xmr_derive_public_key(ge25519 * r, const ge25519 * deriv, uint32_t idx, const ge25519 * base){
|
||||
bignum256modm s={0};
|
||||
ge25519 p2;
|
||||
ge25519_pniels Bp;
|
||||
ge25519_p1p1 p1;
|
||||
|
||||
xmr_derivation_to_scalar(s, deriv, idx);
|
||||
ge25519_scalarmult_base_niels(&p2, ge25519_niels_base_multiples, s);
|
||||
ge25519_norm(&p2, &p2);
|
||||
|
||||
ge25519_full_to_pniels(&Bp, base);
|
||||
ge25519_pnielsadd_p1p1(&p1, &p2, &Bp, 0);
|
||||
ge25519_p1p1_to_full(r, &p1);
|
||||
}
|
||||
|
||||
void xmr_add_keys2(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B){
|
||||
// aG + bB, G is basepoint
|
||||
ge25519 aG, bB;
|
||||
ge25519_pniels bBn;
|
||||
ge25519_p1p1 p1;
|
||||
ge25519_scalarmult_base_niels(&aG, ge25519_niels_base_multiples, a);
|
||||
ge25519_scalarmult(&bB, B, b);
|
||||
ge25519_norm(&bB, &bB);
|
||||
ge25519_norm(&aG, &aG);
|
||||
|
||||
ge25519_full_to_pniels(&bBn, &bB);
|
||||
ge25519_pnielsadd_p1p1(&p1, &aG, &bBn, 0);
|
||||
ge25519_p1p1_to_full(r, &p1);
|
||||
}
|
||||
|
||||
void xmr_add_keys2_vartime(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B){
|
||||
// aG + bB, G is basepoint
|
||||
ge25519_double_scalarmult_vartime(r, B, b, a);
|
||||
ge25519_norm(r, r);
|
||||
}
|
||||
|
||||
void xmr_add_keys3(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B){
|
||||
// aA + bB
|
||||
ge25519 aA, bB;
|
||||
ge25519_pniels bBn;
|
||||
ge25519_p1p1 p1;
|
||||
ge25519_scalarmult(&aA, A, a);
|
||||
ge25519_scalarmult(&bB, B, b);
|
||||
ge25519_norm(&bB, &bB);
|
||||
ge25519_norm(&aA, &aA);
|
||||
|
||||
ge25519_full_to_pniels(&bBn, &bB);
|
||||
ge25519_pnielsadd_p1p1(&p1, &aA, &bBn, 0);
|
||||
ge25519_p1p1_to_full(r, &p1);
|
||||
}
|
||||
|
||||
void xmr_add_keys3_vartime(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B){
|
||||
// aA + bB
|
||||
ge25519_double_scalarmult_vartime2(r, A, a, B, b);
|
||||
ge25519_norm(r, r);
|
||||
}
|
||||
|
||||
void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, uint32_t minor, const bignum256modm m){
|
||||
const char prefix[] = "SubAddr";
|
||||
unsigned char buff[32];
|
||||
contract256_modm(buff, m);
|
||||
|
||||
char data[sizeof(prefix) + sizeof(buff) + 2 * sizeof(uint32_t)];
|
||||
memcpy(data, prefix, sizeof(prefix));
|
||||
memcpy(data + sizeof(prefix), buff, sizeof(buff));
|
||||
memcpy(data + sizeof(prefix) + sizeof(buff), &major, sizeof(uint32_t));
|
||||
memcpy(data + sizeof(prefix) + sizeof(buff) + sizeof(uint32_t), &minor, sizeof(uint32_t));
|
||||
|
||||
xmr_hash_to_scalar(r, data, sizeof(data));
|
||||
}
|
||||
|
||||
void xmr_gen_c(ge25519 * r, const bignum256modm a, uint64_t amount){
|
||||
// C = aG + bH
|
||||
bignum256modm b={0};
|
||||
set256_modm(b, amount);
|
||||
xmr_add_keys2(r, a, b, &xmr_h);
|
||||
}
|
67
monero/xmr.h
Normal file
67
monero/xmr.h
Normal file
@ -0,0 +1,67 @@
|
||||
//
|
||||
// Created by Dusan Klinec on 10/05/2018.
|
||||
//
|
||||
|
||||
#ifndef TREZOR_CRYPTO_XMR_H
|
||||
#define TREZOR_CRYPTO_XMR_H
|
||||
|
||||
#include <ed25519-donna/ge25519.h>
|
||||
#include "hasher.h"
|
||||
|
||||
extern const ge25519 ALIGN(16) xmr_h;
|
||||
|
||||
typedef unsigned char xmr_key_t[32];
|
||||
|
||||
typedef struct xmr_ctkey {
|
||||
xmr_key_t dest;
|
||||
xmr_key_t mask;
|
||||
} xmr_ctkey_t;
|
||||
|
||||
/* sets H point to r */
|
||||
void ge25519_set_xmr_h(ge25519 *r);
|
||||
|
||||
/* random scalar value */
|
||||
void xmr_random_scalar(bignum256modm m);
|
||||
|
||||
/* cn_fast_hash */
|
||||
void xmr_fast_hash(uint8_t * hash, const void *data, size_t length);
|
||||
|
||||
/* incremental hashing wrappers */
|
||||
void xmr_hasher_init(Hasher * hasher);
|
||||
void xmr_hasher_update(Hasher * hasher, const void *data, size_t length);
|
||||
void xmr_hasher_final(Hasher * hasher, uint8_t * hash);
|
||||
void xmr_hasher_copy(Hasher * dst, const Hasher * src);
|
||||
|
||||
/* H_s(buffer) */
|
||||
void xmr_hash_to_scalar(bignum256modm r, const void *data, size_t length);
|
||||
|
||||
/* H_p(buffer) */
|
||||
void xmr_hash_to_ec(ge25519 *P, const void *data, size_t length);
|
||||
|
||||
/* derivation to scalar value */
|
||||
void xmr_derivation_to_scalar(bignum256modm s, const ge25519 * p, uint32_t output_index);
|
||||
|
||||
/* derivation */
|
||||
void xmr_generate_key_derivation(ge25519 * r, const ge25519 * A, const bignum256modm b);
|
||||
|
||||
/* H_s(derivation || varint(output_index)) + base */
|
||||
void xmr_derive_private_key(bignum256modm s, const ge25519 * deriv, uint32_t idx, const bignum256modm base);
|
||||
|
||||
/* H_s(derivation || varint(output_index))G + base */
|
||||
void xmr_derive_public_key(ge25519 * r, const ge25519 * deriv, uint32_t idx, const ge25519 * base);
|
||||
|
||||
/* aG + bB, G is basepoint */
|
||||
void xmr_add_keys2(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B);
|
||||
void xmr_add_keys2_vartime(ge25519 * r, const bignum256modm a, const bignum256modm b, const ge25519 * B);
|
||||
|
||||
/* aA + bB */
|
||||
void xmr_add_keys3(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B);
|
||||
void xmr_add_keys3_vartime(ge25519 * r, const bignum256modm a, const ge25519 * A, const bignum256modm b, const ge25519 * B);
|
||||
|
||||
/* subaddress secret */
|
||||
void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, uint32_t minor, const bignum256modm m);
|
||||
|
||||
/* Generates Pedersen commitment C = aG + bH */
|
||||
void xmr_gen_c(ge25519 * r, const bignum256modm a, uint64_t amount);
|
||||
|
||||
#endif //TREZOR_CRYPTO_XMR_H
|
@ -58,11 +58,13 @@
|
||||
#include "ed25519-donna/ed25519.h"
|
||||
#include "ed25519-donna/ed25519-donna.h"
|
||||
#include "ed25519-donna/ed25519-keccak.h"
|
||||
#include "ed25519-donna/ge25519.h"
|
||||
#include "script.h"
|
||||
#include "rfc6979.h"
|
||||
#include "address.h"
|
||||
#include "rc4.h"
|
||||
#include "nem.h"
|
||||
#include "monero/monero.h"
|
||||
|
||||
#if VALGRIND
|
||||
/*
|
||||
@ -4808,6 +4810,10 @@ END_TEST
|
||||
#include "test_check_cardano.h"
|
||||
#endif
|
||||
|
||||
#if USE_MONERO
|
||||
#include "test_check_monero.h"
|
||||
#endif
|
||||
|
||||
// define test suite and cases
|
||||
Suite *test_suite(void)
|
||||
{
|
||||
@ -5008,9 +5014,11 @@ Suite *test_suite(void)
|
||||
tcase_add_test(tc, test_ed25519_modl_sub);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
#if USE_MONERO
|
||||
tc = tcase_create("ed25519_ge");
|
||||
tcase_add_test(tc, test_ge25519_double_scalarmult_vartime2);
|
||||
suite_add_tcase(s, tc);
|
||||
#endif
|
||||
|
||||
tc = tcase_create("script");
|
||||
tcase_add_test(tc, test_output_script);
|
||||
@ -5067,6 +5075,47 @@ Suite *test_suite(void)
|
||||
suite_add_tcase(s,tc);
|
||||
#endif
|
||||
|
||||
#if USE_MONERO
|
||||
tc = tcase_create("xmr_base58");
|
||||
tcase_add_test(tc, test_xmr_base58);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("xmr_crypto");
|
||||
tcase_add_test(tc, test_xmr_getset256_modm);
|
||||
tcase_add_test(tc, test_xmr_cmp256_modm);
|
||||
tcase_add_test(tc, test_xmr_copy_check_modm);
|
||||
tcase_add_test(tc, test_xmr_mulsub256_modm);
|
||||
tcase_add_test(tc, test_xmr_muladd256_modm);
|
||||
tcase_add_test(tc, test_xmr_curve25519_set);
|
||||
tcase_add_test(tc, test_xmr_curve25519_consts);
|
||||
tcase_add_test(tc, test_xmr_curve25519_tests);
|
||||
tcase_add_test(tc, test_xmr_curve25519_expand_reduce);
|
||||
tcase_add_test(tc, test_xmr_ge25519_base);
|
||||
tcase_add_test(tc, test_xmr_ge25519_check);
|
||||
tcase_add_test(tc, test_xmr_ge25519_scalarmult_base_wrapper);
|
||||
tcase_add_test(tc, test_xmr_ge25519_scalarmult_wrapper);
|
||||
tcase_add_test(tc, test_xmr_ge25519_ops);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("xmr_xmr");
|
||||
tcase_add_test(tc, test_xmr_check_point);
|
||||
tcase_add_test(tc, test_xmr_h);
|
||||
tcase_add_test(tc, test_xmr_fast_hash);
|
||||
tcase_add_test(tc, test_xmr_hasher);
|
||||
tcase_add_test(tc, test_xmr_hash_to_scalar);
|
||||
tcase_add_test(tc, test_xmr_hash_to_ec);
|
||||
tcase_add_test(tc, test_xmr_derivation_to_scalar);
|
||||
tcase_add_test(tc, test_xmr_generate_key_derivation);
|
||||
tcase_add_test(tc, test_xmr_derive_private_key);
|
||||
tcase_add_test(tc, test_xmr_derive_public_key);
|
||||
tcase_add_test(tc, test_xmr_add_keys2);
|
||||
tcase_add_test(tc, test_xmr_add_keys3);
|
||||
tcase_add_test(tc, test_xmr_get_subaddress_secret_key);
|
||||
tcase_add_test(tc, test_xmr_gen_c);
|
||||
tcase_add_test(tc, test_xmr_varint);
|
||||
tcase_add_test(tc, test_xmr_gen_range_sig);
|
||||
suite_add_tcase(s, tc);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
|
1216
tests/test_check_monero.h
Normal file
1216
tests/test_check_monero.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user