@@ -46,35 +46,24 @@ extern "C"
4646// third party headers
4747
4848// standard headers
49- #include < mutex>
5049
5150#undef MONERO_DEFAULT_LOG_CATEGORY
5251#define MONERO_DEFAULT_LOG_CATEGORY " carrot"
5352
5453namespace carrot
5554{
55+ namespace
56+ {
5657// -------------------------------------------------------------------------------------------------------------------
5758// -------------------------------------------------------------------------------------------------------------------
5859static const ge_p3 H_p3 = crypto::get_H_p3();
5960static const ge_p3 T_p3 = crypto::get_T_p3();
60- static const unsigned char l[32 ] = { // curve order
61- 0xed , 0xd3 , 0xf5 , 0x5c , 0x1a , 0x63 , 0x12 , 0x58 ,
62- 0xd6 , 0x9c , 0xf7 , 0xa2 , 0xde , 0xf9 , 0xde , 0x14 ,
63- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
64- 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 };
65- // -------------------------------------------------------------------------------------------------------------------
66- // -------------------------------------------------------------------------------------------------------------------
67- static const mx25519_impl* get_mx25519_impl ()
68- {
69- static std::once_flag of;
70- static const mx25519_impl *impl;
71- std::call_once (of, [&](){ impl = mx25519_select_impl (MX25519_TYPE_AUTO ); });
72- if (impl == nullptr )
73- throw std::runtime_error (" failed to obtain an mx25519 implementation" );
74- return impl;
75- }
61+ static const mx25519_impl* auto_mx25519_impl = mx25519_select_impl(MX25519_TYPE_AUTO );
7662// -------------------------------------------------------------------------------------------------------------------
7763// -------------------------------------------------------------------------------------------------------------------
64+ /* *
65+ * @brief encrypt and encode 64-bit amount with given encryption XOR mask
66+ */
7867static encrypted_amount_t enc_amount (const xmr_amount amount, const encrypted_amount_t &mask)
7968{
8069 static_assert (sizeof (xmr_amount) == sizeof (encrypted_amount_t ), " " );
@@ -86,6 +75,9 @@ static encrypted_amount_t enc_amount(const xmr_amount amount, const encrypted_am
8675}
8776// -------------------------------------------------------------------------------------------------------------------
8877// -------------------------------------------------------------------------------------------------------------------
78+ /* *
79+ * @brief decode and decrypt 64-bit amount with given encryption XOR mask
80+ */
8981static xmr_amount dec_amount (const encrypted_amount_t &encrypted_amount, const encrypted_amount_t &mask)
9082{
9183 static_assert (sizeof (xmr_amount) == sizeof (encrypted_amount_t ), " " );
@@ -98,17 +90,9 @@ static xmr_amount dec_amount(const encrypted_amount_t &encrypted_amount, const e
9890}
9991// -------------------------------------------------------------------------------------------------------------------
10092// -------------------------------------------------------------------------------------------------------------------
101- template <typename Pid,
102- typename OtherPid = std::conditional_t <std::is_same_v<Pid, payment_id_t >, encrypted_payment_id_t , payment_id_t >>
103- static OtherPid convert_payment_id (const Pid &v)
104- {
105- static_assert (sizeof (Pid) == PAYMENT_ID_BYTES );
106- OtherPid conv;
107- memcpy (&conv, &v, PAYMENT_ID_BYTES );
108- return conv;
109- }
110- // -------------------------------------------------------------------------------------------------------------------
111- // -------------------------------------------------------------------------------------------------------------------
93+ /* *
94+ * @brief calculate x G + y T
95+ */
11296static crypto::public_key scalar_mult_gt (const crypto::ec_scalar &x, const crypto::ec_scalar &y)
11397{
11498 ge_p2 tmp1;
@@ -120,13 +104,13 @@ static crypto::public_key scalar_mult_gt(const crypto::ec_scalar &x, const crypt
120104// -------------------------------------------------------------------------------------------------------------------
121105// -------------------------------------------------------------------------------------------------------------------
122106/* *
123- * brief: create a coinbase FCMP++ onetime address extension pubkey
124- * K^o_ext = k^o_g G + k^o_t T
125- * param: s_sender_receiver_ctx - s^ctx_sr
126- * param: amount - a
127- * param: main_address_spend_pubkey - K^0_s
128- * outparam: sender_extension_pubkey_out - K^o_ext
129- */
107+ * @ brief create a coinbase FCMP++ onetime address extension pubkey
108+ * K^o_ext = k^o_g G + k^o_t T
109+ * @ param s_sender_receiver_ctx - s^ctx_sr
110+ * @ param amount - a
111+ * @ param main_address_spend_pubkey - K^0_s
112+ * @param[out] sender_extension_pubkey_out - K^o_ext
113+ */
130114static void make_carrot_sender_extension_pubkey_coinbase (const crypto::hash &s_sender_receiver_ctx,
131115 const xmr_amount amount,
132116 const crypto::public_key &main_address_spend_pubkey,
@@ -146,12 +130,12 @@ static void make_carrot_sender_extension_pubkey_coinbase(const crypto::hash &s_s
146130// -------------------------------------------------------------------------------------------------------------------
147131// -------------------------------------------------------------------------------------------------------------------
148132/* *
149- * brief: create a non-coinbase FCMP++ onetime address extension pubkey
150- * K^o_ext = k^o_g G + k^o_t T
151- * param: s_sender_receiver_ctx - s^ctx_sr
152- * param: amount_commitment - C_a
153- * outparam: sender_extension_pubkey_out - K^o_ext
154- */
133+ * @ brief create a non-coinbase FCMP++ onetime address extension pubkey
134+ * K^o_ext = k^o_g G + k^o_t T
135+ * @ param s_sender_receiver_ctx - s^ctx_sr
136+ * @ param amount_commitment - C_a
137+ * @param[out] sender_extension_pubkey_out - K^o_ext
138+ */
155139static void make_carrot_sender_extension_pubkey (const crypto::hash &s_sender_receiver_ctx,
156140 const amount_commitment_t &amount_commitment,
157141 crypto::public_key &sender_extension_pubkey_out)
@@ -169,6 +153,9 @@ static void make_carrot_sender_extension_pubkey(const crypto::hash &s_sender_rec
169153}
170154// -------------------------------------------------------------------------------------------------------------------
171155// -------------------------------------------------------------------------------------------------------------------
156+ } // anonymous namespace
157+ // -------------------------------------------------------------------------------------------------------------------
158+ // -------------------------------------------------------------------------------------------------------------------
172159void make_carrot_enote_ephemeral_privkey (const janus_anchor_t &anchor_norm,
173160 const input_context_t &input_context,
174161 const crypto::public_key &address_spend_pubkey,
@@ -185,7 +172,7 @@ void make_carrot_enote_ephemeral_pubkey_cryptonote(const crypto::secret_key &eno
185172 mx25519_pubkey &enote_ephemeral_pubkey_out)
186173{
187174 // D_e = d_e B
188- mx25519_scmul_base (get_mx25519_impl () ,
175+ mx25519_scmul_base (auto_mx25519_impl ,
189176 &enote_ephemeral_pubkey_out,
190177 reinterpret_cast <const mx25519_privkey*>(&enote_ephemeral_privkey));
191178}
@@ -230,7 +217,7 @@ bool try_make_carrot_shared_key_receiver(const crypto::secret_key &k_view,
230217 mx25519_pubkey &s_sender_receiver_out)
231218{
232219 // s_sr = k_v D_e
233- mx25519_scmul_key (get_mx25519_impl () ,
220+ mx25519_scmul_key (auto_mx25519_impl ,
234221 &s_sender_receiver_out,
235222 reinterpret_cast <const mx25519_privkey*>(&k_view),
236223 &enote_ephemeral_pubkey);
@@ -243,21 +230,16 @@ bool try_make_carrot_shared_key_sender(const crypto::secret_key &enote_ephemeral
243230 mx25519_pubkey &s_sender_receiver_out)
244231{
245232 // if K^j_v not in prime order subgroup, then FAIL
246- ge_p3 address_view_pubkey_p3;
247- if (0 != ge_frombytes_vartime (&address_view_pubkey_p3, to_bytes (address_view_pubkey)))
248- return false ;
249- // 0 ?= l * K^j_v
250- ge_p3 tmp1;
251- ge_scalarmult_p3 (&tmp1, l, &address_view_pubkey_p3);
252- if (!ge_p3_is_point_at_infinity_vartime (&tmp1))
233+ if (!verify_point_is_in_main_subgroup (address_view_pubkey))
253234 return false ;
254235
255236 // D^j_v = ConvertPointE(K^j_v)
256237 mx25519_pubkey address_view_pubkey_x25519;
257- ge_p3_to_x25519 (address_view_pubkey_x25519.data , &address_view_pubkey_p3);
238+ if (0 != edwards_bytes_to_x25519_vartime (address_view_pubkey_x25519.data , to_bytes (address_view_pubkey)))
239+ return false ;
258240
259241 // s_sr = d_e D^j_v
260- mx25519_scmul_key (get_mx25519_impl () ,
242+ mx25519_scmul_key (auto_mx25519_impl ,
261243 &s_sender_receiver_out,
262244 reinterpret_cast <const mx25519_privkey*>(&enote_ephemeral_privkey),
263245 &address_view_pubkey_x25519);
@@ -505,7 +487,9 @@ encrypted_payment_id_t encrypt_legacy_payment_id(const payment_id_t payment_id,
505487 make_carrot_payment_id_encryption_mask (s_sender_receiver_ctx, onetime_address, mask);
506488
507489 // pid_enc = pid XOR m_pid
508- return convert_payment_id (payment_id) ^ mask;
490+ encrypted_payment_id_t payment_id_conv;
491+ memcpy (&payment_id_conv, &payment_id, sizeof (payment_id_conv));
492+ return payment_id_conv ^ mask;
509493}
510494// -------------------------------------------------------------------------------------------------------------------
511495payment_id_t decrypt_legacy_payment_id (const encrypted_payment_id_t encrypted_payment_id,
@@ -517,7 +501,10 @@ payment_id_t decrypt_legacy_payment_id(const encrypted_payment_id_t encrypted_pa
517501 make_carrot_payment_id_encryption_mask (s_sender_receiver_ctx, onetime_address, mask);
518502
519503 // pid = pid_enc XOR m_pid
520- return convert_payment_id (encrypted_payment_id ^ mask);
504+ mask = mask ^ encrypted_payment_id;
505+ payment_id_t payment_id;
506+ memcpy (&payment_id, &mask, sizeof (payment_id));
507+ return payment_id;
521508}
522509// -------------------------------------------------------------------------------------------------------------------
523510void make_carrot_janus_anchor_special (const mx25519_pubkey &enote_ephemeral_pubkey,
@@ -663,12 +650,18 @@ bool verify_carrot_normal_janus_protection(const janus_anchor_t &nominal_anchor,
663650// -------------------------------------------------------------------------------------------------------------------
664651bool verify_point_is_in_main_subgroup (const crypto::ec_point &P)
665652{
653+ constexpr unsigned char curve_order[32 ] = {
654+ 0xed , 0xd3 , 0xf5 , 0x5c , 0x1a , 0x63 , 0x12 , 0x58 ,
655+ 0xd6 , 0x9c , 0xf7 , 0xa2 , 0xde , 0xf9 , 0xde , 0x14 ,
656+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
657+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x10 };
658+
666659 // valid point?
667660 ge_p3 p3;
668661 if (0 != ge_frombytes_vartime (&p3, to_bytes (P)))
669662 return false ;
670663 // 0 ?= l * K^j_v
671- ge_scalarmult_p3 (&p3, l , &p3);
664+ ge_scalarmult_p3 (&p3, curve_order , &p3);
672665 return ge_p3_is_point_at_infinity_vartime (&p3);
673666}
674667// -------------------------------------------------------------------------------------------------------------------
0 commit comments