From c8b6a4d3c6d6c62193c3f6551bd16808e917b833 Mon Sep 17 00:00:00 2001 From: rishflab Date: Mon, 19 Apr 2021 15:51:10 +1000 Subject: [PATCH] hash_to_scalar working with c bindings --- CMakeLists.txt | 11 + monero-adaptor/depend/hash/hash.c | 151 +++++++++--- monero-adaptor/depend/hash/hash.h | 1 - monero-adaptor/depend/hash/int-util.h | 339 ++++++++++++++++++++++++++ monero-adaptor/src/lib.rs | 7 +- 5 files changed, 473 insertions(+), 36 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 monero-adaptor/depend/hash/int-util.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..8d2477a7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,11 @@ +cmake_minimum_required(VERSION 3.19) +project(xmr_btc_swap_comit C) + +set(CMAKE_C_STANDARD 11) + +include_directories(monero-adaptor/depend/hash) + +add_library(xmr_btc_swap_comit + monero-adaptor/depend/hash/hash.c + monero-adaptor/depend/hash/hash.h + monero-adaptor/depend/hash/int-util.h) diff --git a/monero-adaptor/depend/hash/hash.c b/monero-adaptor/depend/hash/hash.c index d74eb186..e97c6ec5 100644 --- a/monero-adaptor/depend/hash/hash.c +++ b/monero-adaptor/depend/hash/hash.c @@ -4,34 +4,101 @@ #include "hash.h" #include #include +#include "int-util.h" -static void local_abort(const char *msg) -{ - fprintf(stderr, "%s\n", msg); +#ifndef ROTL64 +#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) +#endif + +static void local_abort(const char *msg) { + fprintf(stderr, "%s\n", msg); #ifdef NDEBUG - _exit(1); + _exit(1); #else - abort(); + abort(); #endif } + typedef uint64_t state_t[25]; + void hash_to_scalar(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen) { - keccak(in, inlen, md, mdlen); - sc_reduce32(md); + keccak(in, inlen, md, mdlen); + sc_reduce32(md); } -void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen) -{ +const uint64_t keccakf_rndc[24] = + { + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 + }; + +const int keccakf_rotc[24] = + { + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 + }; + +const int keccakf_piln[24] = + { + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 + }; + + +void keccakf(uint64_t st[25], int rounds) { + int i, j, round; + uint64_t t, bc[5]; + + for (round = 0; round < rounds; round++) { + + // Theta + for (i = 0; i < 5; i++) + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; + + for (i = 0; i < 5; i++) { + t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); + for (j = 0; j < 25; j += 5) + st[j + i] ^= t; + } + + // Rho Pi + t = st[1]; + for (i = 0; i < 24; i++) { + j = keccakf_piln[i]; + bc[0] = st[j]; + st[j] = ROTL64(t, keccakf_rotc[i]); + t = bc[0]; + } + + // Chi + for (j = 0; j < 25; j += 5) { + for (i = 0; i < 5; i++) + bc[i] = st[j + i]; + for (i = 0; i < 5; i++) + st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; + } + + // Iota + st[0] ^= keccakf_rndc[round]; + } +} + +void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen) { state_t st; uint8_t temp[144]; size_t i, rsiz, rsizw; static_assert(HASH_DATA_AREA <= sizeof(temp), "Bad keccak preconditions"); - if (mdlen <= 0 || (mdlen > 100 && sizeof(st) != (size_t)mdlen)) - { - local_abort("Bad keccak use"); + if (mdlen <= 0 || (mdlen > 100 && sizeof(st) != (size_t) mdlen)) { + local_abort("Bad keccak use"); } rsiz = sizeof(state_t) == mdlen ? HASH_DATA_AREA : 200 - 2 * mdlen; @@ -40,22 +107,21 @@ void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen) memset(st, 0, sizeof(st)); for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) { - for (i = 0; i < rsizw; i++) { - uint64_t ina; - memcpy(&ina, in + i * 8, 8); - st[i] ^= swap64le(ina); - } - keccakf(st, KECCAK_ROUNDS); + for (i = 0; i < rsizw; i++) { + uint64_t ina; + memcpy(&ina, in + i * 8, 8); + st[i] ^= swap64le(ina); + } + keccakf(st, KECCAK_ROUNDS); } // last block and padding - if (inlen + 1 >= sizeof(temp) || inlen > rsiz || rsiz - inlen + inlen + 1 >= sizeof(temp) || rsiz == 0 || rsiz - 1 >= sizeof(temp) || rsizw * 8 > sizeof(temp)) - { - local_abort("Bad keccak use"); + if (inlen + 1 >= sizeof(temp) || inlen > rsiz || rsiz - inlen + inlen + 1 >= sizeof(temp) || rsiz == 0 || rsiz - 1 >= sizeof(temp) || rsizw * 8 > sizeof(temp)) { + local_abort("Bad keccak use"); } if (inlen > 0) - memcpy(temp, in, inlen); + memcpy(temp, in, inlen); temp[inlen++] = 1; memset(temp + inlen, 0, rsiz - inlen); temp[rsiz - 1] |= 0x80; @@ -65,22 +131,39 @@ void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen) keccakf(st, KECCAK_ROUNDS); - if (((size_t)mdlen % sizeof(uint64_t)) != 0) - { - local_abort("Bad keccak use"); + if (((size_t) mdlen % sizeof(uint64_t)) != 0) { + local_abort("Bad keccak use"); } - memcpy_swap64le(md, st, mdlen/sizeof(uint64_t)); + memcpy_swap64le(md, st, mdlen / sizeof(uint64_t)); } +uint64_t load_3(const unsigned char *in) { + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + return result; +} + +uint64_t load_4(const unsigned char *in) { + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + result |= ((uint64_t) in[3]) << 24; + return result; +} + + void sc_reduce32(unsigned char *s) { - int64_t s0 = 2097151 & load_3(s); - int64_t s1 = 2097151 & (load_4(s + 2) >> 5); - int64_t s2 = 2097151 & (load_3(s + 5) >> 2); - int64_t s3 = 2097151 & (load_4(s + 7) >> 7); - int64_t s4 = 2097151 & (load_4(s + 10) >> 4); - int64_t s5 = 2097151 & (load_3(s + 13) >> 1); - int64_t s6 = 2097151 & (load_4(s + 15) >> 6); - int64_t s7 = 2097151 & (load_3(s + 18) >> 3); + int64_t s0 = 2097151 & load_3(s); + int64_t s1 = 2097151 & (load_4(s + 2) >> 5); + int64_t s2 = 2097151 & (load_3(s + 5) >> 2); + int64_t s3 = 2097151 & (load_4(s + 7) >> 7); + int64_t s4 = 2097151 & (load_4(s + 10) >> 4); + int64_t s5 = 2097151 & (load_3(s + 13) >> 1); + int64_t s6 = 2097151 & (load_4(s + 15) >> 6); + int64_t s7 = 2097151 & (load_3(s + 18) >> 3); int64_t s8 = 2097151 & load_3(s + 21); int64_t s9 = 2097151 & (load_4(s + 23) >> 5); int64_t s10 = 2097151 & (load_3(s + 26) >> 2); diff --git a/monero-adaptor/depend/hash/hash.h b/monero-adaptor/depend/hash/hash.h index 730e7775..c6d42810 100644 --- a/monero-adaptor/depend/hash/hash.h +++ b/monero-adaptor/depend/hash/hash.h @@ -17,7 +17,6 @@ enum { HASH_DATA_AREA = 136 }; -void hash_to_scalar(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen); void keccak(const uint8_t *in, size_t inlen, uint8_t *md, int mdlen); void sc_reduce32(unsigned char *); diff --git a/monero-adaptor/depend/hash/int-util.h b/monero-adaptor/depend/hash/int-util.h new file mode 100644 index 00000000..92e2ccf7 --- /dev/null +++ b/monero-adaptor/depend/hash/int-util.h @@ -0,0 +1,339 @@ +// Copyright (c) 2014-2020, 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 +#include +#include +#include + +#ifndef _MSC_VER + +#include + +#endif + +#if defined(__ANDROID__) +#include +#endif + +#if defined(__sun) && defined(__SVR4) +#include +#endif + +#if defined(_MSC_VER) +#include + +static inline uint32_t rol32(uint32_t x, int r) { + static_assert(sizeof(uint32_t) == sizeof(unsigned int), "this code assumes 32-bit integers"); + return _rotl(x, r); +} + +static inline uint64_t rol64(uint64_t x, int r) { + return _rotl64(x, r); +} + +#else + +static inline uint32_t rol32(uint32_t x, int r) { + return (x << (r & 31)) | (x >> (-r & 31)); +} + +static inline uint64_t rol64(uint64_t x, int r) { + return (x << (r & 63)) | (x >> (-r & 63)); +} + +#endif + +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; +} + +static inline uint64_t div_with_reminder(uint64_t dividend, uint32_t divisor, uint32_t *remainder) { + dividend |= ((uint64_t) *remainder) << 32; + *remainder = dividend % divisor; + return dividend / divisor; +} + +// Long division with 2^32 base +static inline uint32_t +div128_32(uint64_t dividend_hi, uint64_t dividend_lo, uint32_t divisor, uint64_t *quotient_hi, uint64_t *quotient_lo) { + uint64_t dividend_dwords[4]; + uint32_t remainder = 0; + + dividend_dwords[3] = hi_dword(dividend_hi); + dividend_dwords[2] = lo_dword(dividend_hi); + dividend_dwords[1] = hi_dword(dividend_lo); + dividend_dwords[0] = lo_dword(dividend_lo); + + *quotient_hi = div_with_reminder(dividend_dwords[3], divisor, &remainder) << 32; + *quotient_hi |= div_with_reminder(dividend_dwords[2], divisor, &remainder); + *quotient_lo = div_with_reminder(dividend_dwords[1], divisor, &remainder) << 32; + *quotient_lo |= div_with_reminder(dividend_dwords[0], divisor, &remainder); + + return remainder; +} + +// Long divisor with 2^64 base +void +div128_64(uint64_t dividend_hi, uint64_t dividend_lo, uint64_t divisor, uint64_t *quotient_hi, uint64_t *quotient_lo, + uint64_t *remainder_hi, uint64_t *remainder_lo); + +static inline void add64clamp(uint64_t *value, uint64_t add) { + static const uint64_t maxval = (uint64_t) -1; + if (*value > maxval - add) + *value = maxval; + else + *value += add; +} + +static inline void sub64clamp(uint64_t *value, uint64_t sub) { + if (*value < sub) + *value = 0; + else + *value -= sub; +} + +#define IDENT16(x) ((uint16_t) (x)) +#define IDENT32(x) ((uint32_t) (x)) +#define IDENT64(x) ((uint64_t) (x)) + +#define SWAP16(x) ((((uint16_t) (x) & 0x00ff) << 8) | \ + (((uint16_t) (x) & 0xff00) >> 8)) +#define SWAP32(x) ((((uint32_t) (x) & 0x000000ff) << 24) | \ + (((uint32_t) (x) & 0x0000ff00) << 8) | \ + (((uint32_t) (x) & 0x00ff0000) >> 8) | \ + (((uint32_t) (x) & 0xff000000) >> 24)) +#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)) + +static inline uint16_t ident16(uint16_t x) { return x; } + +static inline uint32_t ident32(uint32_t x) { return x; } + +static inline uint64_t ident64(uint64_t x) { return x; } + +#ifndef __OpenBSD__ +# if defined(__ANDROID__) && defined(__swap16) && !defined(swap16) +# define swap16 __swap16 +# elif !defined(swap16) + +static inline uint16_t swap16(uint16_t x) { + return ((x & 0x00ff) << 8) | ((x & 0xff00) >> 8); +} + +# endif +# if defined(__ANDROID__) && defined(__swap32) && !defined(swap32) +# define swap32 __swap32 +# elif !defined(swap32) + +static inline uint32_t swap32(uint32_t x) { + x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8); + return (x << 16) | (x >> 16); +} + +# endif +# if defined(__ANDROID__) && defined(__swap64) && !defined(swap64) +# define swap64 __swap64 +# elif !defined(swap64) + +static inline uint64_t swap64(uint64_t x) { + x = ((x & 0x00ff00ff00ff00ff) << 8) | ((x & 0xff00ff00ff00ff00) >> 8); + x = ((x & 0x0000ffff0000ffff) << 16) | ((x & 0xffff0000ffff0000) >> 16); + return (x << 32) | (x >> 32); +} + +# endif +#endif /* __OpenBSD__ */ + +#if defined(__GNUC__) +#define UNUSED __attribute__((unused)) +#else +#define UNUSED +#endif + +static inline void mem_inplace_ident(void *mem UNUSED, size_t n UNUSED) {} + +#undef UNUSED + +static inline void mem_inplace_swap16(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint16_t *) mem)[i] = swap16(((const uint16_t *) mem)[i]); + } +} + +static inline void mem_inplace_swap32(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint32_t *) mem)[i] = swap32(((const uint32_t *) mem)[i]); + } +} + +static inline void mem_inplace_swap64(void *mem, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint64_t *) mem)[i] = swap64(((const uint64_t *) mem)[i]); + } +} + +static inline void memcpy_ident16(void *dst, const void *src, size_t n) { + memcpy(dst, src, 2 * n); +} + +static inline void memcpy_ident32(void *dst, const void *src, size_t n) { + memcpy(dst, src, 4 * n); +} + +static inline void memcpy_ident64(void *dst, const void *src, size_t n) { + memcpy(dst, src, 8 * n); +} + +static inline void memcpy_swap16(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint16_t *) dst)[i] = swap16(((const uint16_t *) src)[i]); + } +} + +static inline void memcpy_swap32(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint32_t *) dst)[i] = swap32(((const uint32_t *) src)[i]); + } +} + +static inline void memcpy_swap64(void *dst, const void *src, size_t n) { + size_t i; + for (i = 0; i < n; i++) { + ((uint64_t *) dst)[i] = swap64(((const uint64_t *) src)[i]); + } +} + +#ifdef _MSC_VER +# define LITTLE_ENDIAN 1234 +# define BIG_ENDIAN 4321 +# define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) +static_assert(false, "BYTE_ORDER is undefined. Perhaps, GNU extensions are not enabled"); +#endif + +#if BYTE_ORDER == LITTLE_ENDIAN +#define SWAP16LE IDENT16 +#define SWAP16BE SWAP16 +#define swap16le ident16 +#define swap16be swap16 +#define mem_inplace_swap16le mem_inplace_ident +#define mem_inplace_swap16be mem_inplace_swap16 +#define memcpy_swap16le memcpy_ident16 +#define memcpy_swap16be memcpy_swap16 +#define SWAP32LE IDENT32 +#define SWAP32BE SWAP32 +#define swap32le ident32 +#define swap32be swap32 +#define mem_inplace_swap32le mem_inplace_ident +#define mem_inplace_swap32be mem_inplace_swap32 +#define memcpy_swap32le memcpy_ident32 +#define memcpy_swap32be memcpy_swap32 +#define SWAP64LE IDENT64 +#define SWAP64BE SWAP64 +#define swap64le ident64 +#define swap64be swap64 +#define mem_inplace_swap64le mem_inplace_ident +#define mem_inplace_swap64be mem_inplace_swap64 +#define memcpy_swap64le memcpy_ident64 +#define memcpy_swap64be memcpy_swap64 +#endif + +#if BYTE_ORDER == BIG_ENDIAN +#define SWAP16BE IDENT16 +#define SWAP16LE SWAP16 +#define swap16be ident16 +#define swap16le swap16 +#define mem_inplace_swap16be mem_inplace_ident +#define mem_inplace_swap16le mem_inplace_swap16 +#define memcpy_swap16be memcpy_ident16 +#define memcpy_swap16le memcpy_swap16 +#define SWAP32BE IDENT32 +#define SWAP32LE SWAP32 +#define swap32be ident32 +#define swap32le swap32 +#define mem_inplace_swap32be mem_inplace_ident +#define mem_inplace_swap32le mem_inplace_swap32 +#define memcpy_swap32be memcpy_ident32 +#define memcpy_swap32le memcpy_swap32 +#define SWAP64BE IDENT64 +#define SWAP64LE SWAP64 +#define swap64be ident64 +#define swap64le swap64 +#define mem_inplace_swap64be mem_inplace_ident +#define mem_inplace_swap64le mem_inplace_swap64 +#define memcpy_swap64be memcpy_ident64 +#define memcpy_swap64le memcpy_swap64 +#endif diff --git a/monero-adaptor/src/lib.rs b/monero-adaptor/src/lib.rs index 08d094d1..4c4f2a10 100644 --- a/monero-adaptor/src/lib.rs +++ b/monero-adaptor/src/lib.rs @@ -2,7 +2,11 @@ #![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] -include!(concat!(env!("OUT_DIR"), "/bindings.rs")); +// include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +extern "C" { + fn hash_to_scalar(i: *const u8, i_len: usize, md: *mut u8, md_len: usize); +} use anyhow::{bail, Result}; use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT; @@ -706,6 +710,7 @@ mod tests2 { fn test_add() { let hash = [0u8; 32]; let mut scalar = [0u8; 32]; + unsafe { hash_to_scalar(&hash as *const u8, 32, &mut scalar as *mut u8, 32) }; dbg!(scalar); }