Electroneum
device_default.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2019, The Monero Project
2 //
3 // All rights reserved.
4 //
5 // Redistribution and use in source and binary forms, with or without modification, are
6 // permitted provided that the following conditions are met:
7 //
8 // 1. Redistributions of source code must retain the above copyright notice, this list of
9 // conditions and the following disclaimer.
10 //
11 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 // of conditions and the following disclaimer in the documentation and/or other
13 // materials provided with the distribution.
14 //
15 // 3. Neither the name of the copyright holder nor the names of its contributors may be
16 // used to endorse or promote products derived from this software without specific
17 // prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
27 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 //
29 
30 
31 
32 
33 #include "device_default.hpp"
34 #include "int-util.h"
38 #include "ringct/rctOps.h"
39 
40 #define ENCRYPTED_PAYMENT_ID_TAIL 0x8d
41 #define CHACHA8_KEY_TAIL 0x8c
42 
43 namespace hw {
44 
45  namespace core {
46 
48 
50 
51  /* ===================================================================== */
52  /* === Misc ==== */
53  /* ===================================================================== */
54  static inline unsigned char *operator &(crypto::ec_scalar &scalar) {
55  return &reinterpret_cast<unsigned char &>(scalar);
56  }
57  static inline const unsigned char *operator &(const crypto::ec_scalar &scalar) {
58  return &reinterpret_cast<const unsigned char &>(scalar);
59  }
60 
61  /* ======================================================================= */
62  /* SETUP/TEARDOWN */
63  /* ======================================================================= */
65  this->name = name;
66  return true;
67  }
69  return this->name;
70  }
71 
72  bool device_default::init(void) {
73  return true;
74  }
76  return true;
77  }
78 
80  return true;
81  }
83  return true;
84  }
85 
87  return device::set_mode(mode);
88  }
89 
90  /* ======================================================================= */
91  /* LOCKER */
92  /* ======================================================================= */
93 
95 
96  bool device_default::try_lock() { return true; }
97 
99 
100  /* ======================================================================= */
101  /* WALLET & ADDRESS */
102  /* ======================================================================= */
103 
104  bool device_default::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) {
105  const crypto::secret_key &view_key = keys.m_view_secret_key;
106  const crypto::secret_key &spend_key = keys.m_spend_secret_key;
108  memcpy(data.data(), &view_key, sizeof(view_key));
109  memcpy(data.data() + sizeof(view_key), &spend_key, sizeof(spend_key));
110  data[sizeof(data) - 1] = CHACHA8_KEY_TAIL;
111  crypto::generate_chacha_key(data.data(), sizeof(data), key, kdf_rounds);
112  return true;
113  }
115  dfns();
116  }
118  dfns();
119  }
120  /* ======================================================================= */
121  /* SUB ADDRESS */
122  /* ======================================================================= */
123 
124  bool device_default::derive_subaddress_public_key(const crypto::public_key &out_key, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_key) {
125  return crypto::derive_subaddress_public_key(out_key, derivation, output_index,derived_key);
126  }
127 
129  if (index.is_zero())
131 
132  // m = Hs(a || index_major || index_minor)
134 
135  // M = m*G
138 
139  // D = B + M
140  crypto::public_key D = rct::rct2pk(rct::addKeys(rct::pk2rct(keys.m_account_address.m_spend_public_key), rct::pk2rct(M)));
141  return D;
142  }
143 
144  std::vector<crypto::public_key> device_default::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) {
145  CHECK_AND_ASSERT_THROW_MES(begin <= end, "begin > end");
146 
147  std::vector<crypto::public_key> pkeys;
148  pkeys.reserve(end - begin);
149  cryptonote::subaddress_index index = {account, begin};
150 
151  ge_p3 p3;
152  ge_cached cached;
153  CHECK_AND_ASSERT_THROW_MES(ge_frombytes_vartime(&p3, (const unsigned char*)keys.m_account_address.m_spend_public_key.data) == 0,
154  "ge_frombytes_vartime failed to convert spend public key");
155  ge_p3_to_cached(&cached, &p3);
156 
157  for (uint32_t idx = begin; idx < end; ++idx)
158  {
159  index.minor = idx;
160  if (index.is_zero())
161  {
162  pkeys.push_back(keys.m_account_address.m_spend_public_key);
163  continue;
164  }
165  crypto::secret_key m = get_subaddress_secret_key(keys.m_view_secret_key, index);
166 
167  // M = m*G
168  ge_scalarmult_base(&p3, (const unsigned char*)m.data);
169 
170  // D = B + M
171  crypto::public_key D;
172  ge_p1p1 p1p1;
173  ge_add(&p1p1, &p3, &cached);
174  ge_p1p1_to_p3(&p3, &p1p1);
175  ge_p3_tobytes((unsigned char*)D.data, &p3);
176 
177  pkeys.push_back(D);
178  }
179  return pkeys;
180  }
181 
182  cryptonote::account_public_address device_default::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
183  if (index.is_zero())
184  return keys.m_account_address;
185 
186  crypto::public_key D = get_subaddress_spend_public_key(keys, index);
187 
188  // C = a*D
189  crypto::public_key C = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(D), rct::sk2rct(keys.m_view_secret_key)));
190 
191  // result: (C, D)
192  cryptonote::account_public_address address;
193  address.m_view_public_key = C;
194  address.m_spend_public_key = D;
195  return address;
196  }
197 
198  crypto::secret_key device_default::get_subaddress_secret_key(const crypto::secret_key &a, const cryptonote::subaddress_index &index) {
199  const char prefix[] = "SubAddr";
200  char data[sizeof(prefix) + sizeof(crypto::secret_key) + 2 * sizeof(uint32_t)];
201  memcpy(data, prefix, sizeof(prefix));
202  memcpy(data + sizeof(prefix), &a, sizeof(crypto::secret_key));
203  uint32_t idx = SWAP32LE(index.major);
204  memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key), &idx, sizeof(uint32_t));
205  idx = SWAP32LE(index.minor);
206  memcpy(data + sizeof(prefix) + sizeof(crypto::secret_key) + sizeof(uint32_t), &idx, sizeof(uint32_t));
207  crypto::secret_key m;
208  crypto::hash_to_scalar(data, sizeof(data), m);
209  return m;
210  }
211 
212  // subaddress pub spend is D = B + mG where m is the subaddress secret key, B is the main wallet public spend key
213  // Alternatively write D = bG + mG === (b+m)G
214  // therefore priv spend d = b+m
215  crypto::secret_key device_default::get_subaddress_private_spendkey(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &subaddr_index){
216  crypto::secret_key subaddr_secret_key = get_subaddress_secret_key(keys.m_view_secret_key, subaddr_index);
217  crypto::secret_key subaddr_private_spendkey;
218  sc_secret_add(subaddr_private_spendkey, subaddr_secret_key, keys.m_spend_secret_key);
219  return subaddr_private_spendkey;
220  }
221 
222  // subaddress pub view is C = aD where 'a' is the main wallet private view key
223  // Alternatively write C = a*dG === a*(b+m)G
224  // therefore priv view c = a(b+m)
225  crypto::secret_key device_default::get_subaddress_private_viewkey(const crypto::secret_key &main_wallet_sec_view, crypto::secret_key &subaddress_sec_spend){
226  crypto::secret_key subaddr_private_viewkey;
227  sc_mul(&subaddr_private_viewkey, &main_wallet_sec_view, &subaddress_sec_spend);
228  return subaddr_private_viewkey;
229  }
230 
231  /* ======================================================================= */
232  /* DERIVATION & KEY */
233  /* ======================================================================= */
234 
235  bool device_default::verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key) {
236  crypto::public_key calculated_pub;
237  bool r = crypto::secret_key_to_public_key(secret_key, calculated_pub);
238  return r && public_key == calculated_pub;
239  }
240 
241  bool device_default::scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) {
242  rct::scalarmultKey(aP, P,a);
243  return true;
244  }
245 
246  bool device_default::scalarmultBase(rct::key &aG, const rct::key &a) {
247  rct::scalarmultBase(aG,a);
248  return true;
249  }
250 
251  bool device_default::sc_secret_add(crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) {
252  sc_add(&r, &a, &b);
253  return true;
254  }
255 
256  crypto::secret_key device_default::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) {
257  return crypto::generate_keys(pub, sec, recovery_key, recover);
258  }
259 
260  bool device_default::generate_key_derivation(const crypto::public_key &key1, const crypto::secret_key &key2, crypto::key_derivation &derivation) {
261  return crypto::generate_key_derivation(key1, key2, derivation);
262  }
263 
264  bool device_default::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res){
265  crypto::derivation_to_scalar(derivation,output_index, res);
266  return true;
267  }
268 
269  bool device_default::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &base, crypto::secret_key &derived_key){
270  crypto::derive_secret_key(derivation, output_index, base, derived_key);
271  return true;
272  }
273 
274  bool device_default::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &base, crypto::public_key &derived_key){
275  return crypto::derive_public_key(derivation, output_index, base, derived_key);
276  }
277 
278  bool device_default::secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) {
279  return crypto::secret_key_to_public_key(sec,pub);
280  }
281 
282  bool device_default::generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image){
283  crypto::generate_key_image(pub, sec,image);
284  return true;
285  }
286 
287  bool device_default::conceal_derivation(crypto::key_derivation &derivation, const crypto::public_key &tx_pub_key, const std::vector<crypto::public_key> &additional_tx_pub_keys, const crypto::key_derivation &main_derivation, const std::vector<crypto::key_derivation> &additional_derivations){
288  return true;
289  }
290 
291  /* ======================================================================= */
292  /* TRANSACTION */
293  /* ======================================================================= */
294  void device_default::generate_tx_proof(const crypto::hash &prefix_hash,
295  const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
296  crypto::signature &sig) {
297  crypto::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
298  }
299 
300  bool device_default::open_tx(crypto::secret_key &tx_key) {
301  cryptonote::keypair txkey = cryptonote::keypair::generate(*this);
302  tx_key = txkey.sec;
303  return true;
304  }
305 
306  bool device_default::generate_output_ephemeral_keys(const size_t tx_version,
307  const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
308  const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index,
309  const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys,
310  std::vector<crypto::public_key> &additional_tx_public_keys,
311  std::vector<rct::key> &amount_keys, crypto::public_key &out_eph_public_key) {
312 
313  crypto::key_derivation derivation;
314 
315  // make additional tx pubkey if necessary
316  cryptonote::keypair additional_txkey;
317  if (need_additional_txkeys)
318  {
319  additional_txkey.sec = additional_tx_keys[output_index];
320  if (dst_entr.is_subaddress)
321  additional_txkey.pub = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(dst_entr.addr.m_spend_public_key), rct::sk2rct(additional_txkey.sec)));
322  else
323  additional_txkey.pub = rct::rct2pk(rct::scalarmultBase(rct::sk2rct(additional_txkey.sec)));
324  }
325 
326  bool r;
327  if (change_addr && dst_entr.addr == *change_addr)
328  {
329  // sending change to yourself; derivation = a*R
330  r = generate_key_derivation(txkey_pub, sender_account_keys.m_view_secret_key, derivation);
331  CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey_pub << ", " << sender_account_keys.m_view_secret_key << ")");
332  }
333  else
334  {
335  // sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
336  r = generate_key_derivation(dst_entr.addr.m_view_public_key, dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key, derivation);
337  CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : tx_key) << ")");
338  }
339 
340  if (need_additional_txkeys)
341  {
342  additional_tx_public_keys.push_back(additional_txkey.pub);
343  }
344 
345  if (tx_version > 1)
346  {
347  crypto::secret_key scalar1;
348  derivation_to_scalar(derivation, output_index, scalar1);
349  amount_keys.push_back(rct::sk2rct(scalar1));
350  }
351  r = derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
352  CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")");
353 
354  return r;
355  }
356 
357  bool device_default::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) {
358  crypto::key_derivation derivation;
359  crypto::hash hash;
360  char data[33]; /* A hash, and an extra byte */
361 
362  if (!generate_key_derivation(public_key, secret_key, derivation))
363  return false;
364 
365  memcpy(data, &derivation, 32);
366  data[32] = ENCRYPTED_PAYMENT_ID_TAIL;
367  cn_fast_hash(data, 33, hash);
368 
369  for (size_t b = 0; b < 8; ++b)
370  payment_id.data[b] ^= hash.data[b];
371 
372  return true;
373  }
374 
375  rct::key device_default::genCommitmentMask(const rct::key &amount_key) {
376  return rct::genCommitmentMask(amount_key);
377  }
378 
379  bool device_default::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & sharedSec, bool short_amount) {
380  rct::ecdhEncode(unmasked, sharedSec, short_amount);
381  return true;
382  }
383 
384  bool device_default::ecdhDecode(rct::ecdhTuple & masked, const rct::key & sharedSec, bool short_amount) {
385  rct::ecdhDecode(masked, sharedSec, short_amount);
386  return true;
387  }
388 
389  bool device_default::mlsag_prepare(const rct::key &H, const rct::key &xx,
390  rct::key &a, rct::key &aG, rct::key &aHP, rct::key &II) {
391  rct::skpkGen(a, aG);
392  rct::scalarmultKey(aHP, H, a);
393  rct::scalarmultKey(II, H, xx);
394  return true;
395  }
396  bool device_default::mlsag_prepare(rct::key &a, rct::key &aG) {
397  rct::skpkGen(a, aG);
398  return true;
399  }
400  bool device_default::mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size, const rct::keyV &hashes, const rct::ctkeyV &outPk, rct::key &prehash) {
401  prehash = rct::cn_fast_hash(hashes);
402  return true;
403  }
404 
405 
406  bool device_default::mlsag_hash(const rct::keyV &toHash, rct::key &c_old) {
407  c_old = rct::hash_to_scalar(toHash);
408  return true;
409  }
410 
411  bool device_default::mlsag_sign(const rct::key &c, const rct::keyV &xx, const rct::keyV &alpha, const size_t rows, const size_t dsRows, rct::keyV &ss ) {
412  CHECK_AND_ASSERT_THROW_MES(dsRows<=rows, "dsRows greater than rows");
413  CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "xx size does not match rows");
414  CHECK_AND_ASSERT_THROW_MES(alpha.size() == rows, "alpha size does not match rows");
415  CHECK_AND_ASSERT_THROW_MES(ss.size() == rows, "ss size does not match rows");
416  for (size_t j = 0; j < rows; j++) {
417  sc_mulsub(ss[j].bytes, c.bytes, xx[j].bytes, alpha[j].bytes);
418  }
419  return true;
420  }
421 
422  bool device_default::close_tx() {
423  return true;
424  }
425 
426  bool device_default::hash_to_scalar(boost::shared_ptr<crypto::rs_comm> buf, size_t length, crypto::ec_scalar &res) {
427  crypto::hash_to_scalar(buf.get(), length, res);
428  return true;
429  }
430 
431  bool device_default::get_transaction_prefix_hash(const cryptonote::transaction_prefix& tx, crypto::hash& tx_prefix_hash) {
432 
433  std::ostringstream s;
434  binary_archive<true> a(s);
435  ::serialization::serialize(a, const_cast<cryptonote::transaction_prefix&>(tx));
436 
437  crypto::cn_fast_hash(s.str().data(), s.str().size(), tx_prefix_hash);
438 
439  return true;
440  }
441 
442  bool device_default::generate_ring_signature(const crypto::hash &prefix_hash, const crypto::key_image &image,
443  const std::vector<const crypto::public_key *> &pubs,
444  const crypto::secret_key &sec, std::size_t sec_index,
445  crypto::signature *sig){
446  crypto::generate_ring_signature(prefix_hash, image, pubs.data(), pubs.size(), sec, sec_index, sig);
447  return true;
448  }
449 
450  bool device_default::generate_input_signature(const crypto::hash &prefix_hash, const uint32_t input_index, const crypto::secret_key sec_view, const crypto::secret_key sec_spend, crypto::signature& signature){
451  crypto::generate_input_signature(prefix_hash, input_index, sec_view, sec_spend, signature);
452  return true;
453  }
454 
455  /* ---------------------------------------------------------- */
456  static device_default *default_core_device = NULL;
457  void register_all(std::map<std::string, std::unique_ptr<device>> &registry) {
458  if (!default_core_device) {
459  default_core_device = new device_default();
460  default_core_device->set_name("default_core_device");
461 
462  }
463  registry.insert(std::make_pair("default", std::unique_ptr<device>(default_core_device)));
464  }
465 
466 
467  }
468 
469 }
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
bool derive_subaddress_public_key(const crypto::public_key &pub, const crypto::key_derivation &derivation, const std::size_t output_index, crypto::public_key &derived_pub) override
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
bool derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub) override
virtual bool set_mode(device_mode mode)
Definition: device.hpp:130
const char * key
Definition: hmac_keccak.cpp:39
void unlock(void) override
const std::string get_name() const override
const char * name
bool connect(void) override
Archiver & operator &(Archiver &ar, Student &s)
device_mode mode
Definition: device.hpp:251
std::string name
Definition: device.hpp:89
bool init(void) override
unsigned int uint32_t
Definition: stdint.h:126
POD_CLASS ec_scalar
Definition: crypto.h:74
bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &result)
Definition: crypto.h:286
void lock(void) override
unsigned __int64 uint64_t
Definition: stdint.h:136
bool try_lock(void) override
Definition: device.cpp:38
#define CHACHA8_KEY_TAIL
POD_CLASS public_key
Definition: crypto.h:76
bool disconnect() override
crypto::secret_key m_view_secret_key
Definition: account.h:45
account_public_address m_account_address
Definition: account.h:43
crypto::secret_key get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) override
void * memcpy(void *a, const void *b, size_t c)
crypto::secret_key m_spend_secret_key
Definition: account.h:44
bool get_secret_keys(crypto::secret_key &viewkey, crypto::secret_key &spendkey) override
int ge_frombytes_vartime(ge_p3 *, const unsigned char *)
void addKeys(key &AB, const key &A, const key &B)
Definition: rctOps.cpp:420
crypto::public_key get_subaddress_spend_public_key(const cryptonote::account_keys &keys, const cryptonote::subaddress_index &index) override
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
const char * spendkey
Definition: multisig.cpp:38
#define dfns()
Definition: device.hpp:65
bool set_name(const std::string &name) override
std::vector< crypto::public_key > get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) override
bool generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) override
bool generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) override
bool get_public_address(cryptonote::account_public_address &pubkey) override
bool set_mode(device_mode mode) override
int rows
Definition: crypto.h:86