aboutsummaryrefslogtreecommitdiff
path: root/src/crypto
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/crypto/crypto-ops.c50
-rw-r--r--src/crypto/crypto-ops.h2
-rw-r--r--src/crypto/crypto.h11
-rw-r--r--src/crypto/rx-slow-hash.c5
-rw-r--r--src/cryptonote_basic/account.cpp5
-rw-r--r--src/cryptonote_basic/account.h1
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp21
-rw-r--r--src/cryptonote_config.h4
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp1
9 files changed, 82 insertions, 18 deletions
diff --git a/src/crypto/crypto-ops.c b/src/crypto/crypto-ops.c
index 508709280..54ca39775 100644
--- a/src/crypto/crypto-ops.c
+++ b/src/crypto/crypto-ops.c
@@ -3830,15 +3830,51 @@ int sc_isnonzero(const unsigned char *s) {
s[27] | s[28] | s[29] | s[30] | s[31]) - 1) >> 8) + 1;
}
-int ge_p3_is_point_at_infinity(const ge_p3 *p) {
- // X = 0 and Y == Z
- int n;
- for (n = 0; n < 10; ++n)
+int ge_p3_is_point_at_infinity_vartime(const ge_p3 *p) {
+ // https://eprint.iacr.org/2008/522
+ // X == T == 0 and Y/Z == 1
+ // note: convert all pieces to canonical bytes in case rounding is required (i.e. an element is > q)
+ // note2: even though T = XY/Z is true for valid point representations (implying it isn't necessary to
+ // test T == 0), the input to this function might NOT be valid, so we must test T == 0
+ char result_X_bytes[32];
+ fe_tobytes((unsigned char*)&result_X_bytes, p->X);
+
+ // X != 0
+ for (int i = 0; i < 32; ++i)
{
- if (p->X[n] | p->T[n])
+ if (result_X_bytes[i])
return 0;
- if (p->Y[n] != p->Z[n])
+ }
+
+ char result_T_bytes[32];
+ fe_tobytes((unsigned char*)&result_T_bytes, p->T);
+
+ // T != 0
+ for (int i = 0; i < 32; ++i)
+ {
+ if (result_T_bytes[i])
+ return 0;
+ }
+
+ char result_Y_bytes[32];
+ char result_Z_bytes[32];
+ fe_tobytes((unsigned char*)&result_Y_bytes, p->Y);
+ fe_tobytes((unsigned char*)&result_Z_bytes, p->Z);
+
+ // Y != Z
+ for (int i = 0; i < 32; ++i)
+ {
+ if (result_Y_bytes[i] != result_Z_bytes[i])
return 0;
}
- return 1;
+
+ // is Y nonzero? then Y/Z == 1
+ for (int i = 0; i < 32; ++i)
+ {
+ if (result_Y_bytes[i] != 0)
+ return 1;
+ }
+
+ // Y/Z = 0/0
+ return 0;
}
diff --git a/src/crypto/crypto-ops.h b/src/crypto/crypto-ops.h
index 22f76974b..96da16cbd 100644
--- a/src/crypto/crypto-ops.h
+++ b/src/crypto/crypto-ops.h
@@ -162,4 +162,4 @@ void fe_add(fe h, const fe f, const fe g);
void fe_tobytes(unsigned char *, const fe);
void fe_invert(fe out, const fe z);
-int ge_p3_is_point_at_infinity(const ge_p3 *p);
+int ge_p3_is_point_at_infinity_vartime(const ge_p3 *p);
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 7ddc0150f..599ae4f91 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -64,6 +64,11 @@ namespace crypto {
friend class crypto_ops;
};
+ POD_CLASS public_key_memsafe : epee::mlocked<tools::scrubbed<public_key>> {
+ public_key_memsafe() = default;
+ public_key_memsafe(const public_key &original) { memcpy(this->data, original.data, 32); }
+ };
+
using secret_key = epee::mlocked<tools::scrubbed<ec_scalar>>;
POD_CLASS public_keyV {
@@ -100,7 +105,7 @@ namespace crypto {
void random32_unbiased(unsigned char *bytes);
static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
- sizeof(public_key) == 32 && sizeof(secret_key) == 32 &&
+ sizeof(public_key) == 32 && sizeof(public_key_memsafe) == 32 && sizeof(secret_key) == 32 &&
sizeof(key_derivation) == 32 && sizeof(key_image) == 32 &&
sizeof(signature) == 64, "Invalid structure size");
@@ -310,9 +315,13 @@ namespace crypto {
const extern crypto::public_key null_pkey;
const extern crypto::secret_key null_skey;
+
+ inline bool operator<(const public_key &p1, const public_key &p2) { return memcmp(&p1, &p2, sizeof(public_key)) < 0; }
+ inline bool operator>(const public_key &p1, const public_key &p2) { return p2 < p1; }
}
CRYPTO_MAKE_HASHABLE(public_key)
CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(secret_key)
+CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe)
CRYPTO_MAKE_HASHABLE(key_image)
CRYPTO_MAKE_COMPARABLE(signature)
diff --git a/src/crypto/rx-slow-hash.c b/src/crypto/rx-slow-hash.c
index 801987e37..247c9032f 100644
--- a/src/crypto/rx-slow-hash.c
+++ b/src/crypto/rx-slow-hash.c
@@ -63,6 +63,7 @@ static rx_state rx_s[2] = {{CTHR_MUTEX_INIT,{0},0,0},{CTHR_MUTEX_INIT,{0},0,0}};
static randomx_dataset *rx_dataset;
static int rx_dataset_nomem;
+static int rx_dataset_nolp;
static uint64_t rx_dataset_height;
static THREADV randomx_vm *rx_vm = NULL;
@@ -316,10 +317,11 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
}
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
}
- if (!(disabled_flags() & RANDOMX_FLAG_LARGE_PAGES)) {
+ if (!(disabled_flags() & RANDOMX_FLAG_LARGE_PAGES) && !rx_dataset_nolp) {
rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset);
if(rx_vm == NULL) { //large pages failed
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX VM");
+ rx_dataset_nolp = 1;
}
}
if (rx_vm == NULL)
@@ -370,5 +372,6 @@ void rx_stop_mining(void) {
randomx_release_dataset(rd);
}
rx_dataset_nomem = 0;
+ rx_dataset_nolp = 0;
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
}
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
index 36ff41684..9927351a9 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -253,11 +253,6 @@ DISABLE_VS_WARNINGS(4244 4345)
return crypto::secret_key_to_public_key(view_secret_key, m_keys.m_account_address.m_view_public_key);
}
//-----------------------------------------------------------------
- void account_base::finalize_multisig(const crypto::public_key &spend_public_key)
- {
- m_keys.m_account_address.m_spend_public_key = spend_public_key;
- }
- //-----------------------------------------------------------------
const account_keys& account_base::get_keys() const
{
return m_keys;
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
index 5288b9b04..96b024c3c 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
@@ -82,7 +82,6 @@ namespace cryptonote
void create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey);
void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey);
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys);
- void finalize_multisig(const crypto::public_key &spend_public_key);
const account_keys& get_keys() const;
std::string get_public_address_str(network_type nettype) const;
std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const;
diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 17adcdc35..835f59d69 100644
--- a/src/cryptonote_basic/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -306,7 +306,26 @@ namespace cryptonote
{
// derive secret key with subaddress - step 1: original CN derivation
crypto::secret_key scalar_step1;
- hwdev.derive_secret_key(recv_derivation, real_output_index, ack.m_spend_secret_key, scalar_step1); // computes Hs(a*R || idx) + b
+ crypto::secret_key spend_skey = crypto::null_skey;
+
+ if (ack.m_multisig_keys.empty())
+ {
+ // if not multisig, use normal spend skey
+ spend_skey = ack.m_spend_secret_key;
+ }
+ else
+ {
+ // if multisig, use sum of multisig privkeys (local account's share of aggregate spend key)
+ for (const auto &multisig_key : ack.m_multisig_keys)
+ {
+ sc_add((unsigned char*)spend_skey.data,
+ (const unsigned char*)multisig_key.data,
+ (const unsigned char*)spend_skey.data);
+ }
+ }
+
+ // computes Hs(a*R || idx) + b
+ hwdev.derive_secret_key(recv_derivation, real_output_index, spend_skey, scalar_step1);
// step 2: add Hs(a || index_major || index_minor)
crypto::secret_key subaddr_sk;
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index 915835d1b..b738960a3 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -229,6 +229,7 @@ namespace config
const unsigned char HASH_KEY_RPC_PAYMENT_NONCE = 0x58;
const unsigned char HASH_KEY_MEMORY = 'k';
const unsigned char HASH_KEY_MULTISIG[] = {'M', 'u', 'l', 't' , 'i', 's', 'i', 'g', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ const unsigned char HASH_KEY_MULTISIG_KEY_AGGREGATION[] = "Multisig_key_agg";
const unsigned char HASH_KEY_TXPROOF_V2[] = "TXPROOF_V2";
const unsigned char HASH_KEY_CLSAG_ROUND[] = "CLSAG_round";
const unsigned char HASH_KEY_CLSAG_AGG_0[] = "CLSAG_agg_0";
@@ -236,6 +237,9 @@ namespace config
const char HASH_KEY_MESSAGE_SIGNING[] = "MoneroMessageSignature";
const unsigned char HASH_KEY_MM_SLOT = 'm';
+ // Multisig
+ const uint32_t MULTISIG_MAX_SIGNERS{16};
+
namespace testnet
{
uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 53;
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
index f6061b803..a50ebb550 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.cpp
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -43,7 +43,6 @@ using namespace epee;
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "ringct/rctSigs.h"
-#include "multisig/multisig.h"
using namespace crypto;