Electroneum
device_ledger.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 #include "version.h"
31 #include "device_ledger.hpp"
32 #include "ringct/rctOps.h"
36 #include "crypto/crypto.h"
37 
38 #include <boost/thread/locks.hpp>
39 #include <boost/thread/lock_guard.hpp>
40 
41 namespace {
42  static void local_abort(const char *msg)
43  {
44  fprintf(stderr, "%s\n", msg);
45 #ifdef NDEBUG
46  _exit(1);
47 #else
48  abort();
49 #endif
50  }
51 }
52 
53 namespace hw {
54 
55  namespace ledger {
56 
57  #ifdef WITH_DEVICE_LEDGER
58 
59  #undef ELECTRONEUM_DEFAULT_LOG_CATEGORY
60  #define ELECTRONEUM_DEFAULT_LOG_CATEGORY "device.ledger"
61 
62  /* ===================================================================== */
63  /* === Debug ==== */
64  /* ===================================================================== */
65 
66  void set_apdu_verbose(bool verbose) {
67  apdu_verbose = verbose;
68  }
69 
70  #define TRACKD MTRACE("hw")
71  #define ASSERT_SW(sw,ok,msk) CHECK_AND_ASSERT_THROW_MES(((sw)&(mask))==(ok), "Wrong Device Status : SW=" << std::hex << (sw) << " (EXPECT=" << std::hex << (ok) << ", MASK=" << std::hex << (mask) << ")") ;
72  #define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ;
73  #define ASSERT_X(exp,msg) CHECK_AND_ASSERT_THROW_MES(exp, msg);
74 
75  #ifdef DEBUG_HWDEVICE
76  crypto::secret_key dbg_viewkey;
77  crypto::secret_key dbg_spendkey;
78  #endif
79 
80  /* ===================================================================== */
81  /* === hmacmap ==== */
82  /* ===================================================================== */
83 
84 
85  SecHMAC::SecHMAC(const uint8_t s[32], const uint8_t h[32]) {
86  memcpy(this->sec, s, 32);
87  memcpy(this->hmac, h, 32);
88  }
89 
90  void HMACmap::find_mac(const uint8_t sec[32], uint8_t hmac[32]) {
91  size_t sz = hmacs.size();
92  log_hexbuffer("find_mac: lookup for ", (char*)sec,32);
93  for (size_t i=0; i<sz; i++) {
94  log_hexbuffer("find_mac: - try ",(char*)hmacs[i].sec,32);
95  if (memcmp(sec, hmacs[i].sec, 32) == 0) {
96  memcpy(hmac, hmacs[i].hmac, 32);
97  log_hexbuffer("find_mac: - found ",(char*)hmacs[i].hmac,32);
98  return;
99  }
100 
101  }
102  throw std::runtime_error("Protocol error: try to send untrusted secret");
103  }
104 
105  void HMACmap::add_mac(const uint8_t sec[32], const uint8_t hmac[32]) {
106  log_hexbuffer("add_mac: sec ", (char*)sec,32);
107  log_hexbuffer("add_mac: hmac ", (char*)hmac,32);
108  hmacs.push_back(SecHMAC(sec,hmac));
109  }
110 
111  void HMACmap::clear() {
112  hmacs.clear();
113  }
114 
115  /* ===================================================================== */
116  /* === Keymap ==== */
117  /* ===================================================================== */
118 
119  ABPkeys::ABPkeys(const rct::key& A, const rct::key& B, const bool is_subaddr, const bool is_change, const bool need_additional_txkeys, const size_t real_output_index, const rct::key& P, const rct::key& AK) {
120  Aout = A;
121  Bout = B;
122  is_subaddress = is_subaddr;
123  is_change_address = is_change;
124  additional_key = need_additional_txkeys;
125  index = real_output_index;
126  Pout = P;
127 
128  // Comment out this line for now (only used by rct transactions)
129  //AKout = AK;
130  }
131 
132  ABPkeys::ABPkeys(const ABPkeys& keys) {
133  Aout = keys.Aout;
134  Bout = keys.Bout;
135  is_subaddress = keys.is_subaddress;
136  is_change_address = keys.is_change_address;
137  additional_key = keys.additional_key;
138  index = keys.index;
139  Pout = keys.Pout;
140  AKout = keys.AKout;
141  }
142 
143  ABPkeys &ABPkeys::operator=(const ABPkeys& keys) {
144  if (&keys == this)
145  return *this;
146  Aout = keys.Aout;
147  Bout = keys.Bout;
148  is_subaddress = keys.is_subaddress;
149  is_change_address = keys.is_change_address;
150  additional_key = keys.additional_key;
151  index = keys.index;
152  Pout = keys.Pout;
153  AKout = keys.AKout;
154  return *this;
155  }
156 
157  bool Keymap::find(const rct::key& P, ABPkeys& keys) const {
158  size_t sz = ABP.size();
159  for (size_t i=0; i<sz; i++) {
160  if (ABP[i].Pout == P) {
161  keys = ABP[i];
162  return true;
163  }
164  }
165  return false;
166  }
167 
168  void Keymap::add(const ABPkeys& keys) {
169  ABP.push_back(keys);
170  }
171 
172  void Keymap::clear() {
173  ABP.clear();
174  }
175 
176  #ifdef DEBUG_HWDEVICE
177  void Keymap::log() {
178  log_message("keymap", "content");
179  size_t sz = ABP.size();
180  for (size_t i=0; i<sz; i++) {
181  log_message(" keymap", std::to_string(i));
182  log_hexbuffer(" Aout", (char*)ABP[i].Aout.bytes, 32);
183  log_hexbuffer(" Bout", (char*)ABP[i].Bout.bytes, 32);
184  log_message (" is_sub", std::to_string(ABP[i].is_subaddress));
185  log_message (" index", std::to_string(ABP[i].index));
186  log_hexbuffer(" Pout", (char*)ABP[i].Pout.bytes, 32);
187  }
188  }
189  #endif
190 
191  /* ===================================================================== */
192  /* === Internal Helpers ==== */
193  /* ===================================================================== */
194  static bool is_fake_view_key(const crypto::secret_key &sec) {
195  return sec == crypto::null_skey;
196  }
197 
198  bool operator==(const crypto::key_derivation &d0, const crypto::key_derivation &d1) {
199  static_assert(sizeof(crypto::key_derivation) == 32, "key_derivation must be 32 bytes");
200  return !crypto_verify_32((const unsigned char*)&d0, (const unsigned char*)&d1);
201  }
202 
203  /* ===================================================================== */
204  /* === Device ==== */
205  /* ===================================================================== */
206 
207  static int device_id = 0;
208 
209  #define PROTOCOL_VERSION 2
210 
211  #define INS_NONE 0x00
212  #define INS_RESET 0x02
213 
214  #define INS_GET_KEY 0x20
215  #define INS_PUT_KEY 0x22
216  #define INS_GET_CHACHA8_PREKEY 0x24
217  #define INS_VERIFY_KEY 0x26
218 
219  #define INS_SECRET_KEY_TO_PUBLIC_KEY 0x30
220  #define INS_GEN_KEY_DERIVATION 0x32
221  #define INS_DERIVATION_TO_SCALAR 0x34
222  #define INS_DERIVE_PUBLIC_KEY 0x36
223  #define INS_DERIVE_SECRET_KEY 0x38
224  #define INS_GEN_KEY_IMAGE 0x3A
225  #define INS_SECRET_KEY_ADD 0x3C
226  #define INS_SCALAR_MULSUB 0x3D
227  #define INS_SECRET_KEY_SUB 0x3E
228  #define INS_GENERATE_KEYPAIR 0x40
229  #define INS_SECRET_SCAL_MUL_KEY 0x42
230  #define INS_SECRET_SCAL_MUL_BASE 0x44
231 
232  #define INS_DERIVE_SUBADDRESS_PUBLIC_KEY 0x46
233  #define INS_GET_SUBADDRESS 0x48
234  #define INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY 0x4A
235  #define INS_GET_SUBADDRESS_SECRET_KEY 0x4C
236 
237  #define INS_OPEN_TX 0x70
238  #define INS_SET_SIGNATURE_MODE 0x72
239  #define INS_GET_ADDITIONAL_KEY 0x74
240  #define INS_STEALTH 0x76
241  #define INS_GEN_COMMITMENT_MASK 0x77
242  #define INS_BLIND 0x78
243  #define INS_UNBLIND 0x7A
244  #define INS_GEN_TXOUT_KEYS 0x7B
245  #define INS_VALIDATE 0x7C
246  #define INS_MLSAG 0x7E
247  #define INS_CLOSE_TX 0x80
248 
249  #define INS_GET_TX_PROOF 0xA0
250 
251  #define INS_GET_RESPONSE 0xc0
252 
253  #define INS_TX_PREFIX_START 0xD0
254  #define INS_TX_PREFIX_INPUTS 0xD2
255  #define INS_TX_PREFIX_OUTPUTS 0xD4
256  #define INS_TX_PREFIX_OUTPUTS_SIZE 0xD6
257  #define INS_TX_PREFIX_EXTRA 0xD8
258  #define INS_TX_PROMPT_FEE 0xDA
259  #define INS_TX_PROMPT_AMOUNT 0xDC
260 
261  #define INS_HASH_TO_SCALAR 0xE0
262  #define INS_HASH_TO_SCALAR_BATCH 0xE2
263  #define INS_HASH_TO_SCALAR_INIT 0xE4
264 
265  device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 2000) {
266  this->id = device_id++;
267  this->reset_buffer();
268  this->mode = NONE;
269  this->has_view_key = false;
270  this->tx_in_progress = false;
271  MDEBUG( "Device "<<this->id <<" Created");
272  }
273 
274  device_ledger::~device_ledger() {
275  this->release();
276  MDEBUG( "Device "<<this->id <<" Destroyed");
277  }
278 
279  /* ======================================================================= */
280  /* LOCKER */
281  /* ======================================================================= */
282 
283  //automatic lock one more level on device ensuring the current thread is allowed to use it
284  #define AUTO_LOCK_CMD() \
285  /* lock both mutexes without deadlock*/ \
286  boost::lock(device_locker, command_locker); \
287  /* make sure both already-locked mutexes are unlocked at the end of scope */ \
288  boost::lock_guard<boost::recursive_mutex> lock1(device_locker, boost::adopt_lock); \
289  boost::lock_guard<boost::mutex> lock2(command_locker, boost::adopt_lock)
290 
291  //lock the device for a long sequence
292  void device_ledger::lock(void) {
293  MDEBUG( "Ask for LOCKING for device "<<this->name << " in thread ");
294  device_locker.lock();
295  MDEBUG( "Device "<<this->name << " LOCKed");
296  }
297 
298  //lock the device for a long sequence
299  bool device_ledger::try_lock(void) {
300  MDEBUG( "Ask for LOCKING(try) for device "<<this->name << " in thread ");
301  bool r = device_locker.try_lock();
302  if (r) {
303  MDEBUG( "Device "<<this->name << " LOCKed(try)");
304  } else {
305  MDEBUG( "Device "<<this->name << " not LOCKed(try)");
306  }
307  return r;
308  }
309 
310  //lock the device for a long sequence
311  void device_ledger::unlock(void) {
312  try {
313  MDEBUG( "Ask for UNLOCKING for device "<<this->name << " in thread ");
314  } catch (...) {
315  }
316  device_locker.unlock();
317  MDEBUG( "Device "<<this->name << " UNLOCKed");
318  }
319 
320 
321  /* ======================================================================= */
322  /* IO */
323  /* ======================================================================= */
324 
325  #define IO_SW_DENY 0x6982
326  #define IO_SECRET_KEY 0x02
327 
328  void device_ledger::logCMD() {
329  if (apdu_verbose) {
330  char strbuffer[1024];
331  snprintf(strbuffer, sizeof(strbuffer), "%.02x %.02x %.02x %.02x %.02x ",
332  this->buffer_send[0],
333  this->buffer_send[1],
334  this->buffer_send[2],
335  this->buffer_send[3],
336  this->buffer_send[4]
337  );
338  const size_t len = strlen(strbuffer);
339  buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_send+5), this->length_send-5);
340  MDEBUG( "CMD : " << strbuffer);
341  }
342  }
343 
344  void device_ledger::logRESP() {
345  if (apdu_verbose) {
346  char strbuffer[1024];
347  snprintf(strbuffer, sizeof(strbuffer), "%.04x ", this->sw);
348  const size_t len = strlen(strbuffer);
349  buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_recv), this->length_recv);
350  MDEBUG( "RESP : " << strbuffer);
351 
352  }
353  }
354 
355  int device_ledger::set_command_header(unsigned char ins, unsigned char p1, unsigned char p2) {
356  reset_buffer();
357  this->buffer_send[0] = PROTOCOL_VERSION;
358  this->buffer_send[1] = ins;
359  this->buffer_send[2] = p1;
360  this->buffer_send[3] = p2;
361  this->buffer_send[4] = 0x00;
362  return 5;
363  }
364 
365  int device_ledger::set_command_header_noopt(unsigned char ins, unsigned char p1, unsigned char p2) {
366  int offset = set_command_header(ins, p1, p2);
367  //options
368  this->buffer_send[offset++] = 0;
369  this->buffer_send[4] = offset - 5;
370  return offset;
371  }
372 
373  void device_ledger::send_simple(unsigned char ins, unsigned char p1) {
374  this->length_send = set_command_header_noopt(ins, p1);
375  if (ins == INS_GET_KEY && p1 == IO_SECRET_KEY) {
376  // export view key user input
377  this->exchange_wait_on_input();
378  } else {
379  this->exchange();
380  }
381  }
382 
383  void device_ledger::send_secret(const unsigned char sec[32], int &offset) {
384  MDEBUG("send_secret: " << this->tx_in_progress);
385  ASSERT_X(offset + 32 <= BUFFER_SEND_SIZE, "send_secret: out of bounds write (secret)");
386  memmove(this->buffer_send+offset, sec, 32);
387  offset +=32;
388  if (this->tx_in_progress) {
389  ASSERT_X(offset + 32 <= BUFFER_SEND_SIZE, "send_secret: out of bounds write (mac)");
390  this->hmac_map.find_mac((uint8_t*)sec, this->buffer_send+offset);
391  offset += 32;
392  }
393  }
394 
395  void device_ledger::receive_secret(unsigned char sec[32], int &offset) {
396  MDEBUG("receive_secret: " << this->tx_in_progress);
397  ASSERT_X(offset + 32 <= BUFFER_RECV_SIZE, "receive_secret: out of bounds read (secret)");
398  memmove(sec, this->buffer_recv+offset, 32);
399  offset += 32;
400  if (this->tx_in_progress) {
401  ASSERT_X(offset + 32 <= BUFFER_RECV_SIZE, "receive_secret: out of bounds read (mac)");
402  this->hmac_map.add_mac((uint8_t*)sec, this->buffer_recv+offset);
403  offset += 32;
404  }
405  }
406 
407  bool device_ledger::reset() {
408  reset_buffer();
409  int offset = set_command_header_noopt(INS_RESET);
410  const size_t verlen = strlen(ELECTRONEUM_VERSION);
411  ASSERT_X(offset + verlen <= BUFFER_SEND_SIZE, "ELECTRONEUM_VERSION is too long")
412  memmove(this->buffer_send+offset, ELECTRONEUM_VERSION, verlen);
413  offset += strlen(ELECTRONEUM_VERSION);
414  this->buffer_send[4] = offset-5;
415  this->length_send = offset;
416  this->exchange();
417 
418  ASSERT_X(this->length_recv>=3, "Communication error, less than three bytes received. Check your application version.");
419 
420  unsigned int device_version = 0;
421  device_version = VERSION(this->buffer_recv[0], this->buffer_recv[1], this->buffer_recv[2]);
422 
423  ASSERT_X (device_version >= MINIMAL_APP_VERSION,
424  "Unsupported device application version: " << VERSION_MAJOR(device_version)<<"."<<VERSION_MINOR(device_version)<<"."<<VERSION_MICRO(device_version) <<
425  " At least " << MINIMAL_APP_VERSION_MAJOR<<"."<<MINIMAL_APP_VERSION_MINOR<<"."<<MINIMAL_APP_VERSION_MICRO<<" is required.");
426 
427  return true;
428  }
429 
430  unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) {
431  logCMD();
432 
433  this->length_recv = hw_device.exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE, false);
434  ASSERT_X(this->length_recv>=2, "Communication error, less than tow bytes received");
435 
436  this->length_recv -= 2;
437  this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1];
438  logRESP();
439  ASSERT_SW(this->sw,ok,msk);
440 
441  return this->sw;
442  }
443 
444  unsigned int device_ledger::exchange_wait_on_input(unsigned int ok, unsigned int mask) {
445  logCMD();
446  unsigned int deny = 0;
447  this->length_recv = hw_device.exchange(this->buffer_send, this->length_send, this->buffer_recv, BUFFER_SEND_SIZE, true);
448  ASSERT_X(this->length_recv>=2, "Communication error, less than two bytes received");
449 
450  this->length_recv -= 2;
451  this->sw = (this->buffer_recv[length_recv]<<8) | this->buffer_recv[length_recv+1];
452  if (this->sw == IO_SW_DENY) {
453  // cancel on device
454  deny = 1;
455  } else {
456  ASSERT_SW(this->sw,ok,msk);
457  }
458 
459  logRESP();
460  return deny;
461  }
462 
463  void device_ledger::reset_buffer() {
464  this->length_send = 0;
465  memset(this->buffer_send, 0, BUFFER_SEND_SIZE);
466  this->length_recv = 0;
467  memset(this->buffer_recv, 0, BUFFER_RECV_SIZE);
468  }
469 
470  /* ======================================================================= */
471  /* SETUP/TEARDOWN */
472  /* ======================================================================= */
473 
474  bool device_ledger::set_name(const std::string & name) {
475  this->name = name;
476  return true;
477  }
478 
479  const std::string device_ledger::get_name() const {
480  if (!this->connected()) {
481  return std::string("<disconnected:").append(this->name).append(">");
482  }
483  return this->name;
484  }
485 
486  bool device_ledger::init(void) {
487  #ifdef DEBUG_HWDEVICE
488  this->controle_device = &hw::get_device("default");
489  #endif
490  this->release();
491  hw_device.init();
492  MDEBUG( "Device "<<this->id <<" HIDUSB inited");
493  return true;
494  }
495 
496  static const std::vector<hw::io::hid_conn_params> known_devices {
497  {0x2c97, 0x0001, 0, 0xffa0},
498  {0x2c97, 0x0004, 0, 0xffa0},
499  };
500 
501  bool device_ledger::connect(void) {
502  this->disconnect();
503  hw_device.connect(known_devices);
504  this->reset();
505  #ifdef DEBUG_HWDEVICE
507  this->get_public_address(pubkey);
508  #endif
509  crypto::secret_key vkey;
510  crypto::secret_key skey;
511  this->get_secret_keys(vkey,skey);
512 
513  return true;
514  }
515 
516  bool device_ledger::connected(void) const {
517  return hw_device.connected();
518  }
519 
520  bool device_ledger::disconnect() {
521  hw_device.disconnect();
522  return true;
523  }
524 
525  bool device_ledger::release() {
526  this->disconnect();
527  hw_device.release();
528  return true;
529  }
530 
531  bool device_ledger::set_mode(device_mode mode) {
532  AUTO_LOCK_CMD();
533 
534  int offset;
535 
536  switch(mode) {
537  case TRANSACTION_CREATE_REAL:
538  case TRANSACTION_CREATE_FAKE:
539  offset = set_command_header_noopt(INS_SET_SIGNATURE_MODE, 1);
540  //account
541  this->buffer_send[offset] = mode;
542  offset += 1;
543 
544  this->buffer_send[4] = offset-5;
545  this->length_send = offset;
546  this->exchange();
547 
548  this->mode = mode;
549  break;
550 
551  case TRANSACTION_PARSE:
552  case NONE:
553  this->mode = mode;
554  break;
555  default:
556  CHECK_AND_ASSERT_THROW_MES(false, " device_ledger::set_mode(unsigned int mode): invalid mode: "<<mode);
557  }
558  MDEBUG("Switch to mode: " <<mode);
559  return device::set_mode(mode);
560  }
561 
562 
563  /* ======================================================================= */
564  /* WALLET & ADDRESS */
565  /* ======================================================================= */
566 
567  bool device_ledger::get_public_address(cryptonote::account_public_address &pubkey){
568  AUTO_LOCK_CMD();
569 
570  send_simple(INS_GET_KEY, 1);
571 
572  memmove(pubkey.m_view_public_key.data, this->buffer_recv, 32);
573  memmove(pubkey.m_spend_public_key.data, this->buffer_recv+32, 32);
574 
575  return true;
576  }
577 
578  bool device_ledger::get_secret_keys(crypto::secret_key &vkey , crypto::secret_key &skey) {
579  AUTO_LOCK_CMD();
580 
581  //secret key are represented as fake key on the wallet side
582  memset(vkey.data, 0x00, 32);
583  memset(skey.data, 0xFF, 32);
584 
585  //spcialkey, normal conf handled in decrypt
586  send_simple(INS_GET_KEY, 0x02);
587 
588  //View key is retrievied, if allowed, to speed up blockchain parsing
589  memmove(this->viewkey.data, this->buffer_recv+0, 32);
590  if (is_fake_view_key(this->viewkey)) {
591  MDEBUG("Have Not view key");
592  this->has_view_key = false;
593  } else {
594  MDEBUG("Have view key");
595  this->has_view_key = true;
596  }
597 
598  #ifdef DEBUG_HWDEVICE
599  send_simple(INS_GET_KEY, 0x04);
600  memmove(dbg_viewkey.data, this->buffer_recv+0, 32);
601  memmove(dbg_spendkey.data, this->buffer_recv+32, 32);
602  #endif
603 
604  return true;
605  }
606 
607  bool device_ledger::generate_chacha_key(const cryptonote::account_keys &keys, crypto::chacha_key &key, uint64_t kdf_rounds) {
608  AUTO_LOCK_CMD();
609 
610  #ifdef DEBUG_HWDEVICE
611  crypto::chacha_key key_x;
613  this->controle_device->generate_chacha_key(keys_x, key_x, kdf_rounds);
614  #endif
615 
616  send_simple(INS_GET_CHACHA8_PREKEY);
617 
618  char prekey[200];
619  memmove(prekey, &this->buffer_recv[0], 200);
620  crypto::generate_chacha_key_prehashed(&prekey[0], sizeof(prekey), key, kdf_rounds);
621 
622  #ifdef DEBUG_HWDEVICE
623  hw::ledger::check32("generate_chacha_key_prehashed", "key", (char*)key_x.data(), (char*)key.data());
624  #endif
625 
626  return true;
627  }
628 
629  /* ======================================================================= */
630  /* SUB ADDRESS */
631  /* ======================================================================= */
632 
633  bool device_ledger::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){
634  AUTO_LOCK_CMD();
635  #ifdef DEBUG_HWDEVICE
636  const crypto::public_key pub_x = pub;
637  crypto::key_derivation derivation_x;
638  if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
639  derivation_x = derivation;
640  } else {
641  derivation_x = hw::ledger::decrypt(derivation);
642  }
643  const std::size_t output_index_x = output_index;
644  crypto::public_key derived_pub_x;
645  log_hexbuffer("derive_subaddress_public_key: [[IN]] pub ", pub_x.data, 32);
646  log_hexbuffer("derive_subaddress_public_key: [[IN]] derivation", derivation_x.data, 32);
647  log_message ("derive_subaddress_public_key: [[IN]] index ", std::to_string((int)output_index_x));
648  this->controle_device->derive_subaddress_public_key(pub_x, derivation_x,output_index_x,derived_pub_x);
649  log_hexbuffer("derive_subaddress_public_key: [[OUT]] derived_pub", derived_pub_x.data, 32);
650  #endif
651 
652  if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
653  //If we are in TRANSACTION_PARSE, the given derivation has been retrieved uncrypted (wihtout the help
654  //of the device), so continue that way.
655  MDEBUG( "derive_subaddress_public_key : PARSE mode with known viewkey");
656  crypto::derive_subaddress_public_key(pub, derivation, output_index,derived_pub);
657  } else {
658 
659  int offset = set_command_header_noopt(INS_DERIVE_SUBADDRESS_PUBLIC_KEY);
660  //pub
661  memmove(this->buffer_send+offset, pub.data, 32);
662  offset += 32;
663  //derivation
664  this->send_secret((unsigned char*)derivation.data, offset);
665  //index
666  this->buffer_send[offset+0] = output_index>>24;
667  this->buffer_send[offset+1] = output_index>>16;
668  this->buffer_send[offset+2] = output_index>>8;
669  this->buffer_send[offset+3] = output_index>>0;
670  offset += 4;
671 
672  this->buffer_send[4] = offset-5;
673  this->length_send = offset;
674  this->exchange();
675 
676  //pub key
677  memmove(derived_pub.data, &this->buffer_recv[0], 32);
678  }
679  #ifdef DEBUG_HWDEVICE
680  hw::ledger::check32("derive_subaddress_public_key", "derived_pub", derived_pub_x.data, derived_pub.data);
681  #endif
682 
683  return true;
684  }
685 
686  crypto::public_key device_ledger::get_subaddress_spend_public_key(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
687  AUTO_LOCK_CMD();
689 
690  #ifdef DEBUG_HWDEVICE
691  const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys);
692  const cryptonote::subaddress_index index_x = index;
693  crypto::public_key D_x;
694  log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data,32);
695  log_hexbuffer("get_subaddress_spend_public_key: [[IN]] keys.m_spend_secret_key", keys_x.m_spend_secret_key.data,32);
696  log_message ("get_subaddress_spend_public_key: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor));
697  D_x = this->controle_device->get_subaddress_spend_public_key(keys_x, index_x);
698  log_hexbuffer("get_subaddress_spend_public_key: [[OUT]] derivation ", D_x.data, 32);
699  #endif
700 
701  if (index.is_zero()) {
703  } else {
704 
705  int offset = set_command_header_noopt(INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY);
706  //index
707  static_assert(sizeof(cryptonote::subaddress_index) == 8, "cryptonote::subaddress_index shall be 8 bytes length");
708  memmove(this->buffer_send+offset, &index, sizeof(cryptonote::subaddress_index));
709  offset +=8 ;
710 
711  this->buffer_send[4] = offset-5;
712  this->length_send = offset;
713  this->exchange();
714 
715  memmove(D.data, &this->buffer_recv[0], 32);
716  }
717 
718  #ifdef DEBUG_HWDEVICE
719  hw::ledger::check32("get_subaddress_spend_public_key", "D", D_x.data, D.data);
720  #endif
721 
722  return D;
723  }
724 
725  std::vector<crypto::public_key> device_ledger::get_subaddress_spend_public_keys(const cryptonote::account_keys &keys, uint32_t account, uint32_t begin, uint32_t end) {
726  std::vector<crypto::public_key> pkeys;
727  cryptonote::subaddress_index index = {account, begin};
729  for (uint32_t idx = begin; idx < end; ++idx) {
730  index.minor = idx;
731  D = this->get_subaddress_spend_public_key(keys, index);
732  pkeys.push_back(D);
733  }
734  return pkeys;
735  }
736 
737  cryptonote::account_public_address device_ledger::get_subaddress(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &index) {
738  AUTO_LOCK_CMD();
740 
741  #ifdef DEBUG_HWDEVICE
742  const cryptonote::account_keys keys_x = hw::ledger::decrypt(keys);
743  const cryptonote::subaddress_index index_x = index;
745  log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32);
746  log_hexbuffer("get_subaddress: [[IN]] keys.m_view_public_key", keys_x.m_account_address.m_view_public_key.data, 32);
747  log_hexbuffer("get_subaddress: [[IN]] keys.m_view_secret_key ", keys_x.m_view_secret_key.data, 32);
748  log_hexbuffer("get_subaddress: [[IN]] keys.m_spend_public_key", keys_x.m_account_address.m_spend_public_key.data, 32);
749  log_message ("get_subaddress: [[IN]] index ", std::to_string(index_x.major)+"."+std::to_string(index_x.minor));
750  address_x = this->controle_device->get_subaddress(keys_x, index_x);
751  log_hexbuffer("get_subaddress: [[OUT]] keys.m_view_public_key ", address_x.m_view_public_key.data, 32);
752  log_hexbuffer("get_subaddress: [[OUT]] keys.m_spend_public_key", address_x.m_spend_public_key.data, 32);
753  #endif
754 
755  if (index.is_zero()) {
756  address = keys.m_account_address;
757  } else {
758  int offset = set_command_header_noopt(INS_GET_SUBADDRESS);
759  //index
760  static_assert(sizeof(cryptonote::subaddress_index) == 8, "cryptonote::subaddress_index shall be 8 bytes length");
761  memmove(this->buffer_send+offset, &index, sizeof(cryptonote::subaddress_index));
762  offset +=8 ;
763 
764  this->buffer_send[4] = offset-5;
765  this->length_send = offset;
766  this->exchange();
767 
768  memmove(address.m_view_public_key.data, &this->buffer_recv[0], 32);
769  memmove(address.m_spend_public_key.data, &this->buffer_recv[32], 32);
770  }
771 
772  #ifdef DEBUG_HWDEVICE
773  hw::ledger::check32("get_subaddress", "address.m_view_public_key.data", address_x.m_view_public_key.data, address.m_view_public_key.data);
774  hw::ledger::check32("get_subaddress", "address.m_spend_public_key.data", address_x.m_spend_public_key.data, address.m_spend_public_key.data);
775  #endif
776 
777  return address;
778  }
779 
780  crypto::secret_key device_ledger::get_subaddress_secret_key(const crypto::secret_key &sec, const cryptonote::subaddress_index &index) {
781  AUTO_LOCK_CMD();
782  crypto::secret_key sub_sec;
783 
784  #ifdef DEBUG_HWDEVICE
785  const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
786  const cryptonote::subaddress_index index_x = index;
787  crypto::secret_key sub_sec_x;
788  log_message ("get_subaddress_secret_key: [[IN]] index ", std::to_string(index.major)+"."+std::to_string(index.minor));
789  log_hexbuffer("get_subaddress_secret_key: [[IN]] sec ", sec_x.data, 32);
790  sub_sec_x = this->controle_device->get_subaddress_secret_key(sec_x, index_x);
791  log_hexbuffer("get_subaddress_secret_key: [[OUT]] sub_sec", sub_sec_x.data, 32);
792  #endif
793 
794  int offset = set_command_header_noopt(INS_GET_SUBADDRESS_SECRET_KEY);
795  //sec
796  this->send_secret((unsigned char*)sec.data, offset);
797  //index
798  static_assert(sizeof(cryptonote::subaddress_index) == 8, "cryptonote::subaddress_index shall be 8 bytes length");
799  memmove(this->buffer_send+offset, &index, sizeof(cryptonote::subaddress_index));
800  offset +=8 ;
801 
802  this->buffer_send[4] = offset-5;
803  this->length_send = offset;
804  this->exchange();
805 
806  offset = 0;
807  this->receive_secret((unsigned char*)sub_sec.data, offset);
808 
809  #ifdef DEBUG_HWDEVICE
810  crypto::secret_key sub_sec_clear = hw::ledger::decrypt(sub_sec);
811  hw::ledger::check32("get_subaddress_secret_key", "sub_sec", sub_sec_x.data, sub_sec_clear.data);
812  #endif
813 
814  return sub_sec;
815  }
816 
817  crypto::secret_key device_ledger::get_subaddress_private_spendkey(const cryptonote::account_keys& keys, const cryptonote::subaddress_index &subaddr_index){
818  return boost::value_initialized<crypto::secret_key>(); //todo
819  }
820 
821  crypto::secret_key device_ledger::get_subaddress_private_viewkey(const crypto::secret_key &main_wallet_sec_view, crypto::secret_key &subaddress_sec_spend) {
822  return boost::value_initialized<crypto::secret_key>(); //todo
823  }
824 
825  /* ======================================================================= */
826  /* DERIVATION & KEY */
827  /* ======================================================================= */
828 
829  bool device_ledger::verify_keys(const crypto::secret_key &secret_key, const crypto::public_key &public_key) {
830  AUTO_LOCK_CMD();
831  int offset;
832 
833  offset = set_command_header_noopt(INS_VERIFY_KEY);
834  //sec
835  this->send_secret((unsigned char*)secret_key.data, offset);
836  //pub
837  memmove(this->buffer_send+offset, public_key.data, 32);
838  offset += 32;
839 
840  this->buffer_send[4] = offset-5;
841  this->length_send = offset;
842  this->exchange();
843 
844  uint32_t verified =
845  this->buffer_recv[0] << 24 |
846  this->buffer_recv[1] << 16 |
847  this->buffer_recv[2] << 8 |
848  this->buffer_recv[3] << 0 ;
849 
850  return verified == 1;
851  }
852 
853  bool device_ledger::scalarmultKey(rct::key & aP, const rct::key &P, const rct::key &a) {
854  AUTO_LOCK_CMD();
855 
856  #ifdef DEBUG_HWDEVICE
857  const rct::key P_x = P;
858  const rct::key a_x = hw::ledger::decrypt(a);
859  rct::key aP_x;
860  log_hexbuffer("scalarmultKey: [[IN]] P ", (char*)P_x.bytes, 32);
861  log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32);
862  this->controle_device->scalarmultKey(aP_x, P_x, a_x);
863  log_hexbuffer("scalarmultKey: [[OUT]] aP", (char*)aP_x.bytes, 32);
864  #endif
865 
866  int offset = set_command_header_noopt(INS_SECRET_SCAL_MUL_KEY);
867  //pub
868  memmove(this->buffer_send+offset, P.bytes, 32);
869  offset += 32;
870  //sec
871  this->send_secret(a.bytes, offset);
872 
873  this->buffer_send[4] = offset-5;
874  this->length_send = offset;
875  this->exchange();
876 
877  //pub key
878  memmove(aP.bytes, &this->buffer_recv[0], 32);
879 
880  #ifdef DEBUG_HWDEVICE
881  hw::ledger::check32("scalarmultKey", "mulkey", (char*)aP_x.bytes, (char*)aP.bytes);
882  #endif
883 
884  return true;
885  }
886 
888  AUTO_LOCK_CMD();
889 
890  #ifdef DEBUG_HWDEVICE
891  const rct::key a_x = hw::ledger::decrypt(a);
892  rct::key aG_x;
893  log_hexbuffer("scalarmultKey: [[IN]] a ", (char*)a_x.bytes, 32);
894  this->controle_device->scalarmultBase(aG_x, a_x);
895  log_hexbuffer("scalarmultKey: [[OUT]] aG", (char*)aG_x.bytes, 32);
896  #endif
897 
898  int offset = set_command_header_noopt(INS_SECRET_SCAL_MUL_BASE);
899  //sec
900  this->send_secret(a.bytes, offset);
901 
902  this->buffer_send[4] = offset-5;
903  this->length_send = offset;
904  this->exchange();
905 
906  //pub key
907  memmove(aG.bytes, &this->buffer_recv[0], 32);
908 
909  #ifdef DEBUG_HWDEVICE
910  hw::ledger::check32("scalarmultBase", "mulkey", (char*)aG_x.bytes, (char*)aG.bytes);
911  #endif
912 
913  return true;
914  }
915 
916  bool device_ledger::sc_secret_add( crypto::secret_key &r, const crypto::secret_key &a, const crypto::secret_key &b) {
917  AUTO_LOCK_CMD();
918  int offset;
919 
920  #ifdef DEBUG_HWDEVICE
923  crypto::secret_key r_x;
924  rct::key aG_x;
925  log_hexbuffer("sc_secret_add: [[IN]] a ", (char*)a_x.data, 32);
926  log_hexbuffer("sc_secret_add: [[IN]] b ", (char*)b_x.data, 32);
927  this->controle_device->sc_secret_add(r_x, a_x, b_x);
928  log_hexbuffer("sc_secret_add: [[OUT]] aG", (char*)r_x.data, 32);
929  #endif
930 
931  offset = set_command_header_noopt(INS_SECRET_KEY_ADD);
932  //sec key
933  this->send_secret((unsigned char*)a.data, offset);
934  //sec key
935  this->send_secret((unsigned char*)b.data, offset);
936 
937  this->buffer_send[4] = offset-5;
938  this->length_send = offset;
939  this->exchange();
940 
941  //sec key
942  offset = 0;
943  this->receive_secret((unsigned char*)r.data, offset);
944 
945  #ifdef DEBUG_HWDEVICE
947  hw::ledger::check32("sc_secret_add", "r", r_x.data, r_clear.data);
948  #endif
949 
950  return true;
951  }
952 
954  AUTO_LOCK_CMD();
955  int offset;
956 
957  if (recover) {
958  throw std::runtime_error("device generate key does not support recover");
959  }
960 
961  #ifdef DEBUG_HWDEVICE
962  crypto::public_key pub_x;
963  crypto::secret_key sec_x;
964  crypto::secret_key recovery_key_x;
965  if (recover) {
966  recovery_key_x = hw::ledger::decrypt(recovery_key);
967  log_hexbuffer("generate_keys: [[IN]] pub", (char*)recovery_key_x.data, 32);
968  }
969  #endif
970 
971  send_simple(INS_GENERATE_KEYPAIR);
972 
973  offset = 0;
974  //pub key
975  memmove(pub.data, &this->buffer_recv[0], 32);
976  offset += 32;
977  this->receive_secret((unsigned char*)sec.data, offset);
978 
979  #ifdef DEBUG_HWDEVICE
980  crypto::secret_key sec_clear = hw::ledger::decrypt(sec);
981  sec_x = sec_clear;
982  log_hexbuffer("generate_keys: [[OUT]] pub", (char*)pub.data, 32);
983  log_hexbuffer("generate_keys: [[OUT]] sec", (char*)sec_clear.data, 32);
984 
986  hw::ledger::check32("generate_keys", "pub", pub_x.data, pub.data);
987  #endif
988 
989  return sec;
990 
991  }
992 
993  bool device_ledger::mulsub_eqx(crypto::ec_scalar& r, const crypto::ec_scalar& c, const crypto::ec_scalar& x, const crypto::ec_scalar& q){
994 
995  bool res = false;
996 
997  int offset = set_command_header_noopt(INS_SCALAR_MULSUB);
998  //c_s
999  memmove(this->buffer_send+offset, c.data, 32);
1000  offset += 32;
1001 
1002  this->send_secret((unsigned char*)x.data, offset);
1003  this->send_secret((unsigned char*)q.data, offset);
1004 
1005  this->buffer_send[4] = offset-5;
1006  this->length_send = offset;
1007  this->exchange();
1008 
1009  //r for closing the loop
1010  memmove(r.data, &this->buffer_recv[0], 32);
1011 
1012  res = true;
1013  return res;
1014  }
1015 
1017  AUTO_LOCK_CMD();
1018  bool r = false;
1019 
1020  #ifdef DEBUG_HWDEVICE
1021  const crypto::public_key pub_x = pub;
1022  const crypto::secret_key sec_x = (sec == rct::rct2sk(rct::I)) ? sec: hw::ledger::decrypt(sec);
1023  crypto::key_derivation derivation_x;
1024  log_hexbuffer("generate_key_derivation: [[IN]] pub ", pub_x.data, 32);
1025  log_hexbuffer("generate_key_derivation: [[IN]] sec ", sec_x.data, 32);
1026  this->controle_device->generate_key_derivation(pub_x, sec_x, derivation_x);
1027  log_hexbuffer("generate_key_derivation: [[OUT]] derivation", derivation_x.data, 32);
1028  #endif
1029 
1030  if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
1031  //A derivation is resquested in PASRE mode and we have the view key,
1032  //so do that wihtout the device and return the derivation unencrypted.
1033  MDEBUG( "generate_key_derivation : PARSE mode with known viewkey");
1034  //Note derivation in PARSE mode can only happen with viewkey, so assert it!
1035  assert(is_fake_view_key(sec));
1036  r = crypto::generate_key_derivation(pub, this->viewkey, derivation);
1037  } else {
1038  int offset = set_command_header_noopt(INS_GEN_KEY_DERIVATION);
1039  //pub
1040  memmove(this->buffer_send+offset, pub.data, 32);
1041  offset += 32;
1042  //sec
1043  this->send_secret((unsigned char*)sec.data, offset);
1044 
1045  this->buffer_send[4] = offset-5;
1046  this->length_send = offset;
1047  this->exchange();
1048 
1049  offset = 0;
1050  //derivattion data
1051  this->receive_secret((unsigned char*)derivation.data, offset);
1052 
1053  r = true;
1054  }
1055  #ifdef DEBUG_HWDEVICE
1056  crypto::key_derivation derivation_clear ;
1057  if ((this->mode == TRANSACTION_PARSE) && has_view_key) {
1058  derivation_clear = derivation;
1059  } else {
1060  derivation_clear = hw::ledger::decrypt(derivation);
1061  }
1062  hw::ledger::check32("generate_key_derivation", "derivation", derivation_x.data, derivation_clear.data);
1063  #endif
1064 
1065  return r;
1066  }
1067 
1068  bool device_ledger::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) {
1069  const crypto::public_key *pkey=NULL;
1070  if (derivation == main_derivation) {
1071  pkey = &tx_pub_key;
1072  MDEBUG("conceal derivation with main tx pub key");
1073  } else {
1074  for(size_t n=0; n < additional_derivations.size();++n) {
1075  if(derivation == additional_derivations[n]) {
1076  pkey = &additional_tx_pub_keys[n];
1077  MDEBUG("conceal derivation with additionnal tx pub key");
1078  break;
1079  }
1080  }
1081  }
1082  ASSERT_X(pkey, "Mismatched derivation on scan info");
1083  return this->generate_key_derivation(*pkey, crypto::null_skey, derivation);
1084  }
1085 
1087  AUTO_LOCK_CMD();
1088 
1089  #ifdef DEBUG_HWDEVICE
1090  const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
1091  const size_t output_index_x = output_index;
1092  crypto::ec_scalar res_x;
1093  log_hexbuffer("derivation_to_scalar: [[IN]] derivation ", derivation_x.data, 32);
1094  log_message ("derivation_to_scalar: [[IN]] output_index ", std::to_string(output_index_x));
1095  this->controle_device->derivation_to_scalar(derivation_x, output_index_x, res_x);
1096  log_hexbuffer("derivation_to_scalar: [[OUT]] res ", res_x.data, 32);
1097  #endif
1098 
1099  int offset = set_command_header_noopt(INS_DERIVATION_TO_SCALAR);
1100  //derivation
1101  this->send_secret((unsigned char*)derivation.data, offset);
1102 
1103  //index
1104  this->buffer_send[offset+0] = output_index>>24;
1105  this->buffer_send[offset+1] = output_index>>16;
1106  this->buffer_send[offset+2] = output_index>>8;
1107  this->buffer_send[offset+3] = output_index>>0;
1108  offset += 4;
1109 
1110  this->buffer_send[4] = offset-5;
1111  this->length_send = offset;
1112  this->exchange();
1113 
1114  //derivation data
1115  offset = 0;
1116  this->receive_secret((unsigned char*)res.data, offset);
1117 
1118  #ifdef DEBUG_HWDEVICE
1120  hw::ledger::check32("derivation_to_scalar", "res", res_x.data, res_clear.data);
1121  #endif
1122 
1123  return true;
1124  }
1125 
1126  bool device_ledger::derive_secret_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::secret_key &sec, crypto::secret_key &derived_sec) {
1127  AUTO_LOCK_CMD();
1128 
1129  #ifdef DEBUG_HWDEVICE
1130  const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
1131  const std::size_t output_index_x = output_index;
1132  const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
1133  crypto::secret_key derived_sec_x;
1134  log_hexbuffer("derive_secret_key: [[IN]] derivation ", derivation_x.data, 32);
1135  log_message ("derive_secret_key: [[IN]] index ", std::to_string(output_index_x));
1136  log_hexbuffer("derive_secret_key: [[IN]] sec ", sec_x.data, 32);
1137  this->controle_device->derive_secret_key(derivation_x, output_index_x, sec_x, derived_sec_x);
1138  log_hexbuffer("derive_secret_key: [[OUT]] derived_sec", derived_sec_x.data, 32);
1139  #endif
1140 
1141  int offset = set_command_header_noopt(INS_DERIVE_SECRET_KEY);
1142  //derivation
1143  this->send_secret((unsigned char*)derivation.data, offset);
1144  //index
1145  this->buffer_send[offset+0] = output_index>>24;
1146  this->buffer_send[offset+1] = output_index>>16;
1147  this->buffer_send[offset+2] = output_index>>8;
1148  this->buffer_send[offset+3] = output_index>>0;
1149  offset += 4;
1150  //sec
1151  this->send_secret((unsigned char*)sec.data, offset);
1152 
1153  this->buffer_send[4] = offset-5;
1154  this->length_send = offset;
1155  this->exchange();
1156 
1157  offset = 0;
1158  //sec key
1159  this->receive_secret((unsigned char*)derived_sec.data, offset);
1160 
1161  #ifdef DEBUG_HWDEVICE
1162  crypto::secret_key derived_sec_clear = hw::ledger::decrypt(derived_sec);
1163  hw::ledger::check32("derive_secret_key", "derived_sec", derived_sec_x.data, derived_sec_clear.data);
1164  #endif
1165 
1166  return true;
1167  }
1168 
1169  bool device_ledger::derive_public_key(const crypto::key_derivation &derivation, const std::size_t output_index, const crypto::public_key &pub, crypto::public_key &derived_pub){
1170  AUTO_LOCK_CMD();
1171 
1172  #ifdef DEBUG_HWDEVICE
1173  const crypto::key_derivation derivation_x = hw::ledger::decrypt(derivation);
1174  const std::size_t output_index_x = output_index;
1175  const crypto::public_key pub_x = pub;
1176  crypto::public_key derived_pub_x;
1177  log_hexbuffer("derive_public_key: [[IN]] derivation ", derivation_x.data, 32);
1178  log_message ("derive_public_key: [[IN]] output_index", std::to_string(output_index_x));
1179  log_hexbuffer("derive_public_key: [[IN]] pub ", pub_x.data, 32);
1180  this->controle_device->derive_public_key(derivation_x, output_index_x, pub_x, derived_pub_x);
1181  log_hexbuffer("derive_public_key: [[OUT]] derived_pub ", derived_pub_x.data, 32);
1182  #endif
1183 
1184  int offset = set_command_header_noopt(INS_DERIVE_PUBLIC_KEY);
1185  //derivation
1186  this->send_secret((unsigned char*)derivation.data, offset);
1187  //index
1188  this->buffer_send[offset+0] = output_index>>24;
1189  this->buffer_send[offset+1] = output_index>>16;
1190  this->buffer_send[offset+2] = output_index>>8;
1191  this->buffer_send[offset+3] = output_index>>0;
1192  offset += 4;
1193  //pub
1194  memmove(this->buffer_send+offset, pub.data, 32);
1195  offset += 32;
1196 
1197  this->buffer_send[4] = offset-5;
1198  this->length_send = offset;
1199  this->exchange();
1200 
1201  //pub key
1202  memmove(derived_pub.data, &this->buffer_recv[0], 32);
1203 
1204  #ifdef DEBUG_HWDEVICE
1205  hw::ledger::check32("derive_public_key", "derived_pub", derived_pub_x.data, derived_pub.data);
1206  #endif
1207 
1208  return true;
1209  }
1210 
1212  AUTO_LOCK_CMD();
1213 
1214  #ifdef DEBUG_HWDEVICE
1215  const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
1216  crypto::public_key pub_x;
1217  log_hexbuffer("secret_key_to_public_key: [[IN]] sec ", sec_x.data, 32);
1218  bool rc = this->controle_device->secret_key_to_public_key(sec_x, pub_x);
1219  log_hexbuffer("secret_key_to_public_key: [[OUT]] pub", pub_x.data, 32);
1220  if (!rc){
1221  log_message("FAIL secret_key_to_public_key", "secret_key rejected");
1222  }
1223  #endif
1224 
1225  int offset = set_command_header_noopt(INS_SECRET_KEY_TO_PUBLIC_KEY);
1226  //sec key
1227  this->send_secret((unsigned char*)sec.data, offset);
1228 
1229  this->buffer_send[4] = offset-5;
1230  this->length_send = offset;
1231  this->exchange();
1232 
1233  //pub key
1234  memmove(pub.data, &this->buffer_recv[0], 32);
1235 
1236  #ifdef DEBUG_HWDEVICE
1237  hw::ledger::check32("secret_key_to_public_key", "pub", pub_x.data, pub.data);
1238  #endif
1239 
1240  return true;
1241  }
1242 
1243  bool device_ledger::generate_key_image(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_image &image){
1244  AUTO_LOCK_CMD();
1245 
1246  #ifdef DEBUG_HWDEVICE
1247  const crypto::public_key pub_x = pub;
1248  const crypto::secret_key sec_x = hw::ledger::decrypt(sec);
1249  crypto::key_image image_x;
1250  log_hexbuffer("generate_key_image: [[IN]] pub ", pub_x.data, 32);
1251  log_hexbuffer("generate_key_image: [[IN]] sec ", sec_x.data, 32);
1252  this->controle_device->generate_key_image(pub_x, sec_x, image_x);
1253  log_hexbuffer("generate_key_image: [[OUT]] image ", image_x.data, 32);
1254  #endif
1255 
1256  int offset = set_command_header_noopt(INS_GEN_KEY_IMAGE);
1257  //pub
1258  memmove(this->buffer_send+offset, pub.data, 32);
1259  offset += 32;
1260  //sec
1261  this->send_secret((unsigned char*)sec.data, offset);
1262 
1263  this->buffer_send[4] = offset-5;
1264  this->length_send = offset;
1265  this->exchange();
1266 
1267  //pub key
1268  memmove(image.data, &this->buffer_recv[0], 32);
1269 
1270  #ifdef DEBUG_HWDEVICE
1271  hw::ledger::check32("generate_key_image", "image", image_x.data, image.data);
1272  #endif
1273 
1274  return true;
1275  }
1276  /* ===================================================================== */
1277  /* === Misc ==== */
1278  /* ===================================================================== */
1279 
1280  static inline unsigned char *operator &(crypto::ec_point &point) {
1281  return &reinterpret_cast<unsigned char &>(point);
1282  }
1283 
1284  static inline const unsigned char *operator &(const crypto::ec_point &point) {
1285  return &reinterpret_cast<const unsigned char &>(point);
1286  }
1287 
1288  static inline unsigned char *operator &(crypto::ec_scalar &scalar) {
1289  return &reinterpret_cast<unsigned char &>(scalar);
1290  }
1291 
1292  static inline const unsigned char *operator &(const crypto::ec_scalar &scalar) {
1293  return &reinterpret_cast<const unsigned char &>(scalar);
1294  }
1295 
1296  /* ======================================================================= */
1297  /* TRANSACTION */
1298  /* ======================================================================= */
1299 
1300  void device_ledger::generate_tx_proof(const crypto::hash &prefix_hash,
1301  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,
1302  crypto::signature &sig) {
1303 
1304  AUTO_LOCK_CMD();
1305 
1306  #ifdef DEBUG_HWDEVICE
1307  const crypto::hash prefix_hash_x = prefix_hash;
1308  const crypto::public_key R_x = R;
1309  const crypto::public_key A_x = A;
1310  const boost::optional<crypto::public_key> B_x = B;
1311  const crypto::public_key D_x = D;
1312  const crypto::secret_key r_x = hw::ledger::decrypt(r);
1313  crypto::signature sig_x;
1314  log_hexbuffer("generate_tx_proof: [[IN]] prefix_hash ", prefix_hash_x.data, 32);
1315  log_hexbuffer("generate_tx_proof: [[IN]] R ", R_x.data, 32);
1316  log_hexbuffer("generate_tx_proof: [[IN]] A ", A_x.data, 32);
1317  if (B_x) {
1318  log_hexbuffer("generate_tx_proof: [[IN]] B ", (*B_x).data, 32);
1319  }
1320  log_hexbuffer("generate_tx_proof: [[IN]] D ", D_x.data, 32);
1321  log_hexbuffer("generate_tx_proof: [[IN]] r ", r_x.data, 32);
1322  #endif
1323 
1324 
1325  int offset = set_command_header(INS_GET_TX_PROOF);
1326  //options
1327  this->buffer_send[offset] = B?0x01:0x00;
1328  offset += 1;
1329  //prefix_hash
1330  memmove(&this->buffer_send[offset], prefix_hash.data, 32);
1331  offset += 32;
1332  // R
1333  memmove(&this->buffer_send[offset], R.data, 32);
1334  offset += 32;
1335  // A
1336  memmove(&this->buffer_send[offset], A.data, 32);
1337  offset += 32;
1338  // B
1339  if (B) {
1340  memmove(&this->buffer_send[offset], (*B).data, 32);
1341  } else {
1342  memset(&this->buffer_send[offset], 0, 32);
1343  }
1344  offset += 32;
1345  // D
1346  memmove(&this->buffer_send[offset], D.data, 32);
1347  offset += 32;
1348  // r
1349  this->send_secret((unsigned char*)r.data, offset);
1350 
1351  this->buffer_send[4] = offset-5;
1352  this->length_send = offset;
1353  this->exchange();
1354 
1355  memmove(sig.c.data, &this->buffer_recv[0], 32);
1356  memmove(sig.r.data, &this->buffer_recv[32], 32);
1357  #ifdef DEBUG_HWDEVICE
1358  log_hexbuffer("GENERATE_TX_PROOF: **c** ", sig.c.data, sizeof( sig.c.data));
1359  log_hexbuffer("GENERATE_TX_PROOF: **r** ", sig.r.data, sizeof( sig.r.data));
1360 
1361  this->controle_device->generate_tx_proof(prefix_hash_x, R_x, A_x, B_x, D_x, r_x, sig_x);
1362  MDEBUG("FAIL is normal if random is not fixed in proof");
1363  hw::ledger::check32("generate_tx_proof", "c", sig_x.c.data, sig.c.data);
1364  hw::ledger::check32("generate_tx_proof", "r", sig_x.r.data, sig.r.data);
1365 
1366  #endif
1367  }
1368 
1369  bool device_ledger::open_tx(crypto::secret_key &tx_key) {
1370  AUTO_LOCK_CMD();
1371  this->lock();
1372  key_map.clear();
1373  hmac_map.clear();
1374  this->tx_in_progress = true;
1375  int offset = set_command_header_noopt(INS_OPEN_TX, 0x01);
1376 
1377  //account
1378  this->buffer_send[offset+0] = 0x00;
1379  this->buffer_send[offset+1] = 0x00;
1380  this->buffer_send[offset+2] = 0x00;
1381  this->buffer_send[offset+3] = 0x00;
1382  offset += 4;
1383 
1384  this->buffer_send[4] = offset-5;
1385  this->length_send = offset;
1386  this->exchange();
1387 
1388  //skip R, receive: r, r_hmac, fake_a, a_hmac, fake_b, hmac_b
1389  unsigned char tmp[32];
1390  offset = 32;
1391  this->receive_secret((unsigned char*)tx_key.data, offset);
1392  this->receive_secret(tmp, offset);
1393  this->receive_secret(tmp, offset);
1394 
1395  #ifdef DEBUG_HWDEVICE
1396  const crypto::secret_key r_x = hw::ledger::decrypt(tx_key);
1397  log_hexbuffer("open_tx: [[OUT]] R ", (char*)&this->buffer_recv[0], 32);
1398  log_hexbuffer("open_tx: [[OUT]] r ", r_x.data, 32);
1399  #endif
1400  return true;
1401  }
1402 
1403  bool device_ledger::encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key) {
1404  AUTO_LOCK_CMD();
1405 
1406  #ifdef DEBUG_HWDEVICE
1407  const crypto::public_key public_key_x = public_key;
1408  const crypto::secret_key secret_key_x = hw::ledger::decrypt(secret_key);
1409  crypto::hash8 payment_id_x = payment_id;
1410  log_hexbuffer("encrypt_payment_id: [[IN]] payment_id ", payment_id_x.data, 32);
1411  log_hexbuffer("encrypt_payment_id: [[IN]] public_key ", public_key_x.data, 32);
1412  log_hexbuffer("encrypt_payment_id: [[IN]] secret_key ", secret_key_x.data, 32);
1413  this->controle_device->encrypt_payment_id(payment_id_x, public_key_x, secret_key_x);
1414  log_hexbuffer("encrypt_payment_id: [[OUT]] payment_id ", payment_id_x.data, 32);
1415  #endif
1416 
1417  int offset = set_command_header_noopt(INS_STEALTH);
1418  //pub
1419  memmove(&this->buffer_send[offset], public_key.data, 32);
1420  offset += 32;
1421  //sec
1422  this->send_secret((unsigned char*)secret_key.data, offset);
1423  //id
1424  memmove(&this->buffer_send[offset], payment_id.data, 8);
1425  offset += 8;
1426 
1427  this->buffer_send[4] = offset-5;
1428  this->length_send = offset;
1429  this->exchange();
1430  memmove(payment_id.data, &this->buffer_recv[0], 8);
1431 
1432  #ifdef DEBUG_HWDEVICE
1433  hw::ledger::check8("stealth", "payment_id", payment_id_x.data, payment_id.data);
1434  #endif
1435 
1436  return true;
1437  }
1438 
1439 
1440  bool device_ledger::generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key,
1441  const cryptonote::tx_destination_entry &dst_entr, const boost::optional<cryptonote::account_public_address> &change_addr, const size_t output_index,
1442  const bool &need_additional_txkeys, const std::vector<crypto::secret_key> &additional_tx_keys,
1443  std::vector<crypto::public_key> &additional_tx_public_keys,
1444  std::vector<rct::key> &amount_keys,
1445  crypto::public_key &out_eph_public_key) {
1446  AUTO_LOCK_CMD();
1447 
1448  #ifdef DEBUG_HWDEVICE
1449  const size_t &tx_version_x = tx_version;
1450  const cryptonote::account_keys sender_account_keys_x = hw::ledger::decrypt(sender_account_keys);
1451  memmove((void*)sender_account_keys_x.m_view_secret_key.data, dbg_viewkey.data, 32);
1452 
1453  const crypto::public_key txkey_pub_x = txkey_pub;
1454  const crypto::secret_key tx_key_x = hw::ledger::decrypt(tx_key);
1455  const cryptonote::tx_destination_entry dst_entr_x = dst_entr;
1456  const boost::optional<cryptonote::account_public_address> change_addr_x = change_addr;
1457  const size_t output_index_x = output_index;
1458  const bool need_additional_txkeys_x = need_additional_txkeys;
1459 
1460  std::vector<crypto::secret_key> additional_tx_keys_x;
1461  for (const auto k: additional_tx_keys) {
1462  additional_tx_keys_x.push_back(hw::ledger::decrypt(k));
1463  }
1464 
1465  std::vector<crypto::public_key> additional_tx_public_keys_x;
1466  std::vector<rct::key> amount_keys_x;
1467  crypto::public_key out_eph_public_key_x;
1468 
1469  log_message ("generate_output_ephemeral_keys: [[IN]] tx_version", std::to_string(tx_version_x));
1470  //log_hexbuffer("generate_output_ephemeral_keys: [[IN]] sender_account_keys.view", sender_account_keys.m_sview_secret_key.data, 32);
1471  //log_hexbuffer("generate_output_ephemeral_keys: [[IN]] sender_account_keys.spend", sender_account_keys.m_spend_secret_key.data, 32);
1472  log_hexbuffer("generate_output_ephemeral_keys: [[IN]] txkey_pub", txkey_pub_x.data, 32);
1473  log_hexbuffer("generate_output_ephemeral_keys: [[IN]] tx_key", tx_key_x.data, 32);
1474  log_hexbuffer("generate_output_ephemeral_keys: [[IN]] dst_entr.view", dst_entr_x.addr.m_view_public_key.data, 32);
1475  log_hexbuffer("generate_output_ephemeral_keys: [[IN]] dst_entr.spend", dst_entr_x.addr.m_spend_public_key.data, 32);
1476  if (change_addr) {
1477  log_hexbuffer("generate_output_ephemeral_keys: [[IN]] change_addr.view", (*change_addr_x).m_view_public_key.data, 32);
1478  log_hexbuffer("generate_output_ephemeral_keys: [[IN]] change_addr.spend", (*change_addr_x).m_spend_public_key.data, 32);
1479  }
1480  log_message ("generate_output_ephemeral_keys: [[IN]] output_index", std::to_string(output_index_x));
1481  log_message ("generate_output_ephemeral_keys: [[IN]] need_additional_txkeys", std::to_string(need_additional_txkeys_x));
1482  if(need_additional_txkeys_x) {
1483  log_hexbuffer("generate_output_ephemeral_keys: [[IN]] additional_tx_keys[oi]", additional_tx_keys_x[output_index].data, 32);
1484  }
1485  this->controle_device->generate_output_ephemeral_keys(tx_version_x, sender_account_keys_x, txkey_pub_x, tx_key_x, dst_entr_x, change_addr_x, output_index_x, need_additional_txkeys_x, additional_tx_keys_x,
1486  additional_tx_public_keys_x, amount_keys_x, out_eph_public_key_x);
1487  if(need_additional_txkeys_x) {
1488  log_hexbuffer("additional_tx_public_keys_x: [[OUT]] additional_tx_public_keys_x", additional_tx_public_keys_x.back().data, 32);
1489  }
1490  if(tx_version > 1) {
1491  log_hexbuffer("generate_output_ephemeral_keys: [[OUT]] amount_keys ", (char*)amount_keys_x.back().bytes, 32);
1492  }
1493  log_hexbuffer("generate_output_ephemeral_keys: [[OUT]] out_eph_public_key ", out_eph_public_key_x.data, 32);
1494  #endif
1495 
1496  //ASSERT_X(tx_version > 1, "TX version not supported"<<tx_version);
1497 
1498  // make additional tx pubkey if necessary
1499  cryptonote::keypair additional_txkey;
1500  if (need_additional_txkeys) {
1501  additional_txkey.sec = additional_tx_keys[output_index];
1502  }
1503 
1504  int offset = set_command_header_noopt(INS_GEN_TXOUT_KEYS);
1505  //tx_version
1506  this->buffer_send[offset+0] = tx_version>>24;
1507  this->buffer_send[offset+1] = tx_version>>16;
1508  this->buffer_send[offset+2] = tx_version>>8;
1509  this->buffer_send[offset+3] = tx_version>>0;
1510  offset += 4;
1511  //tx_key
1512  this->send_secret((unsigned char*)tx_key.data, offset);
1513  //txkey_pub
1514  memmove(&this->buffer_send[offset], txkey_pub.data, 32);
1515  offset += 32;
1516  //Aout
1517  memmove(&this->buffer_send[offset], dst_entr.addr.m_view_public_key.data, 32);
1518  offset += 32;
1519  //Bout
1520  memmove(&this->buffer_send[offset], dst_entr.addr.m_spend_public_key.data, 32);
1521  offset += 32;
1522  //output index
1523  this->buffer_send[offset+0] = output_index>>24;
1524  this->buffer_send[offset+1] = output_index>>16;
1525  this->buffer_send[offset+2] = output_index>>8;
1526  this->buffer_send[offset+3] = output_index>>0;
1527  offset += 4;
1528  //is_change,
1529  bool is_change = (change_addr && dst_entr.addr == *change_addr);
1530  this->buffer_send[offset] = is_change;
1531  offset++;
1532  //is_subaddress
1533  this->buffer_send[offset] = dst_entr.is_subaddress;
1534  offset++;
1535  //need_additional_key
1536  this->buffer_send[offset] = need_additional_txkeys;
1537  offset++;
1538  //additional_tx_key
1539  if (need_additional_txkeys) {
1540  this->send_secret((unsigned char*)additional_txkey.sec.data, offset);
1541  } else {
1542  memset(&this->buffer_send[offset], 0, 32);
1543  offset += 32;
1544  }
1545 
1546  this->buffer_send[4] = offset-5;
1547  this->length_send = offset;
1548  this->exchange();
1549 
1550  offset = 0;
1551  unsigned int recv_len = this->length_recv;
1552 
1553  if (tx_version > 1)
1554  {
1555  ASSERT_X(recv_len>=32, "Not enought data from device");
1556  crypto::secret_key scalar1;
1557  this->receive_secret((unsigned char*)scalar1.data, offset);
1558  amount_keys.push_back(rct::sk2rct(scalar1));
1559  recv_len -= 32;
1560  }
1561  ASSERT_X(recv_len>=32, "Not enought data from device");
1562  memmove(out_eph_public_key.data, &this->buffer_recv[offset], 32);
1563  recv_len -= 32;
1564  offset += 32;
1565 
1566  if (need_additional_txkeys)
1567  {
1568  ASSERT_X(recv_len>=32, "Not enought data from device");
1569  memmove(additional_txkey.pub.data, &this->buffer_recv[offset], 32);
1570  additional_tx_public_keys.push_back(additional_txkey.pub);
1571  offset += 32;
1572  recv_len -= 32;
1573  }
1574 
1575  // add ABPkeys
1576  this->add_output_key_mapping(dst_entr.addr.m_view_public_key, dst_entr.addr.m_spend_public_key, dst_entr.is_subaddress, is_change,
1577  need_additional_txkeys, output_index,
1578  amount_keys.back(), out_eph_public_key);
1579 
1580  #ifdef DEBUG_HWDEVICE
1581  if(tx_version > 1) {
1582  log_hexbuffer("generate_output_ephemeral_keys: clear amount_key", (const char *) hw::ledger::decrypt(amount_keys.back()).bytes, 32);
1583  hw::ledger::check32("generate_output_ephemeral_keys", "amount_key", (const char *) amount_keys_x.back().bytes, (const char *) hw::ledger::decrypt(amount_keys.back()).bytes);
1584  }
1585  if (need_additional_txkeys) {
1586  hw::ledger::check32("generate_output_ephemeral_keys", "additional_tx_key", additional_tx_public_keys_x.back().data, additional_tx_public_keys.back().data);
1587  }
1588  hw::ledger::check32("generate_output_ephemeral_keys", "out_eph_public_key", out_eph_public_key_x.data, out_eph_public_key.data);
1589  #endif
1590 
1591  return true;
1592  }
1593 
1594  bool device_ledger::add_output_key_mapping(const crypto::public_key &Aout, const crypto::public_key &Bout, const bool is_subaddress, const bool is_change,
1595  const bool need_additional, const size_t real_output_index,
1596  const rct::key &amount_key, const crypto::public_key &out_eph_public_key) {
1597  key_map.add(ABPkeys(rct::pk2rct(Aout),rct::pk2rct(Bout), is_subaddress, is_change, need_additional, real_output_index, rct::pk2rct(out_eph_public_key), amount_key));
1598  return true;
1599  }
1600 
1602  #ifdef DEBUG_HWDEVICE
1603  const rct::key AKout_x = hw::ledger::decrypt(AKout);
1604  rct::key mask_x;
1605  mask_x = this->controle_device->genCommitmentMask(AKout_x);
1606  #endif
1607 
1608  rct::key mask;
1609  int offset = set_command_header_noopt(INS_GEN_COMMITMENT_MASK);
1610  // AKout
1611  this->send_secret(AKout.bytes, offset);
1612 
1613  this->buffer_send[4] = offset-5;
1614  this->length_send = offset;
1615  this->exchange();
1616 
1617  memmove(mask.bytes, &this->buffer_recv[0], 32);
1618 
1619  #ifdef DEBUG_HWDEVICE
1620  hw::ledger::check32("genCommitmentMask", "mask", (const char*)mask_x.bytes, (const char*)mask.bytes);
1621  #endif
1622 
1623  return mask;
1624  }
1625 
1626  bool device_ledger::ecdhEncode(rct::ecdhTuple & unmasked, const rct::key & AKout, bool short_amount) {
1627  AUTO_LOCK_CMD();
1628 
1629  #ifdef DEBUG_HWDEVICE
1630  const rct::key AKout_x = hw::ledger::decrypt(AKout);
1631  rct::ecdhTuple unmasked_x = unmasked;
1632  this->controle_device->ecdhEncode(unmasked_x, AKout_x, short_amount);
1633  #endif
1634 
1635  int offset = set_command_header(INS_BLIND);
1636  //options
1637  this->buffer_send[offset] = short_amount?0x02:0x00;
1638  offset += 1;
1639  // AKout
1640  this->send_secret(AKout.bytes, offset);
1641  //mask k
1642  memmove(this->buffer_send+offset, unmasked.mask.bytes, 32);
1643  offset += 32;
1644  //value v
1645  memmove(this->buffer_send+offset, unmasked.amount.bytes, 32);
1646  offset += 32;
1647 
1648  this->buffer_send[4] = offset-5;
1649  this->length_send = offset;
1650  this->exchange();
1651 
1652  memmove(unmasked.amount.bytes, &this->buffer_recv[0], 32);
1653  memmove(unmasked.mask.bytes, &this->buffer_recv[32], 32);
1654 
1655  #ifdef DEBUG_HWDEVICE
1656  MDEBUG("ecdhEncode: Akout: "<<AKout_x);
1657  hw::ledger::check32("ecdhEncode", "amount", (char*)unmasked_x.amount.bytes, (char*)unmasked.amount.bytes);
1658  hw::ledger::check32("ecdhEncode", "mask", (char*)unmasked_x.mask.bytes, (char*)unmasked.mask.bytes);
1659 
1660  log_hexbuffer("Blind AKV input", (char*)&this->buffer_recv[64], 3*32);
1661  #endif
1662 
1663  return true;
1664  }
1665 
1666  bool device_ledger::ecdhDecode(rct::ecdhTuple & masked, const rct::key & AKout, bool short_amount) {
1667  AUTO_LOCK_CMD();
1668 
1669  #ifdef DEBUG_HWDEVICE
1670  const rct::key AKout_x = hw::ledger::decrypt(AKout);
1671  rct::ecdhTuple masked_x = masked;
1672  this->controle_device->ecdhDecode(masked_x, AKout_x, short_amount);
1673  #endif
1674 
1675  int offset = set_command_header(INS_UNBLIND);
1676  //options
1677  this->buffer_send[offset] = short_amount?0x02:0x00;
1678  offset += 1;
1679  // AKout
1680  this->send_secret(AKout.bytes, offset);
1681  //mask k
1682  memmove(this->buffer_send+offset, masked.mask.bytes, 32);
1683  offset += 32;
1684  //value v
1685  memmove(this->buffer_send+offset, masked.amount.bytes, 32);
1686  offset += 32;
1687 
1688  this->buffer_send[4] = offset-5;
1689  this->length_send = offset;
1690  this->exchange();
1691 
1692  memmove(masked.amount.bytes, &this->buffer_recv[0], 32);
1693  memmove(masked.mask.bytes, &this->buffer_recv[32], 32);
1694 
1695  #ifdef DEBUG_HWDEVICE
1696  MDEBUG("ecdhEncode: Akout: "<<AKout_x);
1697  hw::ledger::check32("ecdhDecode", "amount", (char*)masked_x.amount.bytes, (char*)masked.amount.bytes);
1698  hw::ledger::check32("ecdhDecode", "mask", (char*)masked_x.mask.bytes,(char*) masked.mask.bytes);
1699  #endif
1700 
1701  return true;
1702  }
1703 
1704  bool device_ledger::mlsag_prehash(const std::string &blob, size_t inputs_size, size_t outputs_size,
1705  const rct::keyV &hashes, const rct::ctkeyV &outPk,
1706  rct::key &prehash) {
1707  AUTO_LOCK_CMD();
1708  unsigned int data_offset, C_offset, kv_offset, i;
1709  const char *data;
1710 
1711  #ifdef DEBUG_HWDEVICE
1712  const std::string blob_x = blob;
1713  size_t inputs_size_x = inputs_size;
1714  size_t outputs_size_x = outputs_size;
1715  const rct::keyV hashes_x = hashes;
1716  const rct::ctkeyV outPk_x = outPk;
1717  rct::key prehash_x;
1718  this->controle_device->mlsag_prehash(blob_x, inputs_size_x, outputs_size_x, hashes_x, outPk_x, prehash_x);
1719  if (inputs_size) {
1720  log_message("mlsag_prehash", (std::string("inputs_size not null: ") + std::to_string(inputs_size)).c_str());
1721  }
1722  this->key_map.log();
1723  #endif
1724 
1725  data = blob.data();
1726 
1727  // ====== u8 type, varint txnfee ======
1728  int offset = set_command_header(INS_VALIDATE, 0x01, 0x01);
1729  //options
1730  this->buffer_send[offset] = (inputs_size == 0)?0x00:0x80;
1731  offset += 1;
1732 
1733  //type
1734  uint8_t type = data[0];
1735  this->buffer_send[offset] = data[0];
1736  offset += 1;
1737 
1738  //txnfee
1739  data_offset = 1;
1740  while (data[data_offset]&0x80) {
1741  this->buffer_send[offset] = data[data_offset];
1742  offset += 1;
1743  data_offset += 1;
1744  }
1745  this->buffer_send[offset] = data[data_offset];
1746  offset += 1;
1747  data_offset += 1;
1748 
1749  this->buffer_send[4] = offset-5;
1750  this->length_send = offset;
1751  // check fee user input
1752  CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Fee denied on device.");
1753 
1754  //pseudoOuts
1755  if (type == rct::RCTTypeSimple) {
1756  for ( i = 0; i < inputs_size; i++) {
1757  offset = set_command_header(INS_VALIDATE, 0x01, i+2);
1758  //options
1759  this->buffer_send[offset] = (i==inputs_size-1)? 0x00:0x80;
1760  offset += 1;
1761  //pseudoOut
1762  memmove(this->buffer_send+offset, data+data_offset,32);
1763  offset += 32;
1764  data_offset += 32;
1765 
1766  this->buffer_send[4] = offset-5;
1767  this->length_send = offset;
1768  this->exchange();
1769  }
1770  }
1771 
1772  // ====== Aout, Bout, AKout, C, v, k ======
1773  kv_offset = data_offset;
1774  if (type==rct::RCTTypeBulletproof2) {
1775  C_offset = kv_offset+ (8)*outputs_size;
1776  } else {
1777  C_offset = kv_offset+ (32+32)*outputs_size;
1778  }
1779  for ( i = 0; i < outputs_size; i++) {
1780  ABPkeys outKeys;
1781  bool found;
1782 
1783  found = this->key_map.find(outPk[i].dest, outKeys);
1784  if (!found) {
1785  log_hexbuffer("Pout not found", (char*)outPk[i].dest.bytes, 32);
1786  CHECK_AND_ASSERT_THROW_MES(found, "Pout not found");
1787  }
1788  offset = set_command_header(INS_VALIDATE, 0x02, i+1);
1789  //options
1790  this->buffer_send[offset] = (i==outputs_size-1)? 0x00:0x80 ;
1791  this->buffer_send[offset] |= (type==rct::RCTTypeBulletproof2)?0x02:0x00;
1792  offset += 1;
1793  //is_subaddress
1794  this->buffer_send[offset] = outKeys.is_subaddress;
1795  offset++;
1796  //is_change_address
1797  this->buffer_send[offset] = outKeys.is_change_address;
1798  offset++;
1799  //Aout
1800  memmove(this->buffer_send+offset, outKeys.Aout.bytes, 32);
1801  offset+=32;
1802  //Bout
1803  memmove(this->buffer_send+offset, outKeys.Bout.bytes, 32);
1804  offset+=32;
1805  //AKout
1806  this->send_secret(outKeys.AKout.bytes, offset);
1807 
1808  //C
1809  memmove(this->buffer_send+offset, data+C_offset,32);
1810  offset += 32;
1811  C_offset += 32;
1812  if (type==rct::RCTTypeBulletproof2) {
1813  //k
1814  memset(this->buffer_send+offset, 0, 32);
1815  offset += 32;
1816  //v
1817  memset(this->buffer_send+offset, 0, 32);
1818  memmove(this->buffer_send+offset, data+kv_offset,8);
1819  offset += 32;
1820  kv_offset += 8;
1821  } else {
1822  //k
1823  memmove(this->buffer_send+offset, data+kv_offset,32);
1824  offset += 32;
1825  kv_offset += 32;
1826  //v
1827  memmove(this->buffer_send+offset, data+kv_offset,32);
1828  offset += 32;
1829  kv_offset += 32;
1830  }
1831 
1832  this->buffer_send[4] = offset-5;
1833  this->length_send = offset;
1834  // check transaction user input
1835  CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Transaction denied on device.");
1836  #ifdef DEBUG_HWDEVICE
1837  log_hexbuffer("Prehash AKV input", (char*)&this->buffer_recv[64], 3*32);
1838  #endif
1839  }
1840 
1841  // ====== C[], message, proof======
1842  C_offset = kv_offset;
1843  for (i = 0; i < outputs_size; i++) {
1844  offset = set_command_header(INS_VALIDATE, 0x03, i+1);
1845  //options
1846  this->buffer_send[offset] = 0x80 ;
1847  offset += 1;
1848  //C
1849  memmove(this->buffer_send+offset, data+C_offset,32);
1850  offset += 32;
1851  C_offset += 32;
1852 
1853  this->buffer_send[4] = offset-5;
1854  this->length_send = offset;
1855  this->exchange();
1856 
1857  }
1858 
1859  offset = set_command_header_noopt(INS_VALIDATE, 0x03, i+1);
1860  //message
1861  memmove(this->buffer_send+offset, hashes[0].bytes,32);
1862  offset += 32;
1863  //proof
1864  memmove(this->buffer_send+offset, hashes[2].bytes,32);
1865  offset += 32;
1866 
1867  this->buffer_send[4] = offset-5;
1868  this->length_send = offset;
1869  this->exchange();
1870 
1871  memmove(prehash.bytes, this->buffer_recv, 32);
1872 
1873  #ifdef DEBUG_HWDEVICE
1874  hw::ledger::check32("mlsag_prehash", "prehash", (char*)prehash_x.bytes, (char*)prehash.bytes);
1875  #endif
1876 
1877  return true;
1878  }
1879 
1880 
1881  bool device_ledger::mlsag_prepare(const rct::key &H, const rct::key &xx,
1882  rct::key &a, rct::key &aG, rct::key &aHP, rct::key &II) {
1883  AUTO_LOCK_CMD();
1884 
1885  #ifdef DEBUG_HWDEVICE
1886  const rct::key H_x = H;
1887  const rct::key xx_x = hw::ledger::decrypt(xx);
1888  rct::key a_x;
1889  rct::key aG_x;
1890  rct::key aHP_x;
1891  rct::key II_x;
1892  #endif
1893 
1894  int offset = set_command_header_noopt(INS_MLSAG, 0x01);
1895  //value H
1896  memmove(this->buffer_send+offset, H.bytes, 32);
1897  offset += 32;
1898  //mask xin
1899  this->send_secret(xx.bytes, offset);
1900 
1901  this->buffer_send[4] = offset-5;
1902  this->length_send = offset;
1903  this->exchange();
1904 
1905  offset = 0;
1906  this->receive_secret(a.bytes, offset);
1907  memmove(aG.bytes, &this->buffer_recv[offset], 32);
1908  offset +=32;
1909  memmove(aHP.bytes, &this->buffer_recv[offset], 32);
1910  offset +=32;
1911  memmove(II.bytes, &this->buffer_recv[offset], 32);
1912 
1913  #ifdef DEBUG_HWDEVICE
1914  a_x = hw::ledger::decrypt(a);
1915 
1916  rct::scalarmultBase(aG_x, a_x);
1917  rct::scalarmultKey(aHP_x, H_x, a_x);
1918  rct::scalarmultKey(II_x, H_x, xx_x);
1919  hw::ledger::check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes);
1920  hw::ledger::check32("mlsag_prepare", "aHP", (char*)aHP_x.bytes, (char*)aHP.bytes);
1921  hw::ledger::check32("mlsag_prepare", "II", (char*)II_x.bytes, (char*)II.bytes);
1922  #endif
1923 
1924  return true;
1925  }
1926 
1927  bool device_ledger::mlsag_prepare(rct::key &a, rct::key &aG) {
1928  AUTO_LOCK_CMD();
1929  int offset;
1930 
1931  #ifdef DEBUG_HWDEVICE
1932  rct::key a_x;
1933  rct::key aG_x;
1934  #endif
1935 
1936  send_simple(INS_MLSAG, 0x01);
1937 
1938  offset = 0;
1939  this->receive_secret(a.bytes, offset);
1940  memmove(aG.bytes, &this->buffer_recv[offset], 32);
1941 
1942  #ifdef DEBUG_HWDEVICE
1943  a_x = hw::ledger::decrypt(a);
1944  rct::scalarmultBase(aG_x, a_x);
1945  hw::ledger::check32("mlsag_prepare", "AG", (char*)aG_x.bytes, (char*)aG.bytes);
1946  #endif
1947 
1948  return true;
1949  }
1950 
1951  bool device_ledger::mlsag_hash(const rct::keyV &long_message, rct::key &c) {
1952  AUTO_LOCK_CMD();
1953  size_t cnt;
1954 
1955  #ifdef DEBUG_HWDEVICE
1956  const rct::keyV long_message_x = long_message;
1957  rct::key c_x;
1958  this->controle_device->mlsag_hash(long_message_x, c_x);
1959  #endif
1960 
1961  cnt = long_message.size();
1962  for (size_t i = 0; i<cnt; i++) {
1963  int offset = set_command_header(INS_MLSAG, 0x02, i+1);
1964  //options
1965  this->buffer_send[offset] =
1966  (i==(cnt-1))?0x00:0x80; //last
1967  offset += 1;
1968  //msg part
1969  memmove(this->buffer_send+offset, long_message[i].bytes, 32);
1970  offset += 32;
1971 
1972  this->buffer_send[4] = offset-5;
1973  this->length_send = offset;
1974  this->exchange();
1975  }
1976 
1977  memmove(c.bytes, &this->buffer_recv[0], 32);
1978 
1979  #ifdef DEBUG_HWDEVICE
1980  hw::ledger::check32("mlsag_hash", "c", (char*)c_x.bytes, (char*)c.bytes);
1981  #endif
1982 
1983  return true;
1984  }
1985 
1986  bool device_ledger::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) {
1987  AUTO_LOCK_CMD();
1988 
1989  CHECK_AND_ASSERT_THROW_MES(dsRows<=rows, "dsRows greater than rows");
1990  CHECK_AND_ASSERT_THROW_MES(xx.size() == rows, "xx size does not match rows");
1991  CHECK_AND_ASSERT_THROW_MES(alpha.size() == rows, "alpha size does not match rows");
1992  CHECK_AND_ASSERT_THROW_MES(ss.size() == rows, "ss size does not match rows");
1993 
1994  #ifdef DEBUG_HWDEVICE
1995  const rct::key c_x = c;
1996  const rct::keyV xx_x = hw::ledger::decrypt(xx);
1997  const rct::keyV alpha_x = hw::ledger::decrypt(alpha);
1998  const int rows_x = rows;
1999  const int dsRows_x = dsRows;
2000  rct::keyV ss_x(ss.size());
2001  this->controle_device->mlsag_sign(c_x, xx_x, alpha_x, rows_x, dsRows_x, ss_x);
2002  #endif
2003 
2004  for (size_t j = 0; j < dsRows; j++) {
2005  int offset = set_command_header(INS_MLSAG, 0x03, j+1);
2006  //options
2007  this->buffer_send[offset] = 0x00;
2008  if (j==(dsRows-1)) {
2009  this->buffer_send[offset] |= 0x80; //last
2010  }
2011  offset += 1;
2012  //xx
2013  this->send_secret(xx[j].bytes, offset);
2014  //alpa
2015  this->send_secret(alpha[j].bytes, offset);
2016 
2017  this->buffer_send[4] = offset-5;
2018  this->length_send = offset;
2019  this->exchange();
2020 
2021  //ss
2022  memmove(ss[j].bytes, &this->buffer_recv[0], 32);
2023  }
2024 
2025  for (size_t j = dsRows; j < rows; j++) {
2026  sc_mulsub(ss[j].bytes, c.bytes, xx[j].bytes, alpha[j].bytes);
2027  }
2028 
2029  #ifdef DEBUG_HWDEVICE
2030  for (size_t j = 0; j < rows; j++) {
2031  hw::ledger::check32("mlsag_sign", "ss["+std::to_string(j)+"]", (char*)ss_x[j].bytes, (char*)ss[j].bytes);
2032  }
2033  #endif
2034 
2035  return true;
2036  }
2037 
2038  bool device_ledger::close_tx() {
2039  AUTO_LOCK_CMD();
2040  send_simple(INS_CLOSE_TX);
2041  key_map.clear();
2042  hmac_map.clear();
2043  this->tx_in_progress = false;
2044  this->unlock();
2045  return true;
2046  }
2047 
2049 
2050  AUTO_LOCK_CMD();
2051  int size;
2052 
2053 #ifdef DEBUG_HWDEVICE
2054  std::string hex_tx = "";
2055 #endif
2056 
2057  int offset = set_command_header_noopt(INS_TX_PREFIX_START);
2058  //tx_version
2059  this->buffer_send[offset+0] = tx.version>>24;
2060  this->buffer_send[offset+1] = tx.version>>16;
2061  this->buffer_send[offset+2] = tx.version>>8;
2062  this->buffer_send[offset+3] = tx.version>>0;
2063  offset += 4;
2064  //unlock_time
2065  this->buffer_send[offset+0] = tx.unlock_time>>24;
2066  this->buffer_send[offset+1] = tx.unlock_time>>16;
2067  this->buffer_send[offset+2] = tx.unlock_time>>8;
2068  this->buffer_send[offset+3] = tx.unlock_time>>0;
2069  offset += 4;
2070  //vins size
2071  size = tx.vin.size();
2072  this->buffer_send[offset+0] = size>>24;
2073  this->buffer_send[offset+1] = size>>16;
2074  this->buffer_send[offset+2] = size>>8;
2075  this->buffer_send[offset+3] = size>>0;
2076  offset += 4;
2077 
2078  this->buffer_send[4] = offset-5;
2079  this->length_send = offset;
2080  this->exchange();
2081 
2082 #ifdef DEBUG_HWDEVICE
2083  hex_tx += boost::algorithm::hex(std::string(reinterpret_cast<char const*>(this->buffer_recv), this->length_recv));
2084 #endif
2085 
2086  for(size_t i = 0; i < tx.vin.size(); ++i) {
2087  offset = set_command_header_noopt(INS_TX_PREFIX_INPUTS);
2088 
2089  uint64_t amount = boost::get<cryptonote::txin_to_key>(tx.vin[i]).amount;
2090  uint64_t key_offset = boost::get<cryptonote::txin_to_key>(tx.vin[i]).key_offsets[0];
2091  crypto::key_image k_image = boost::get<cryptonote::txin_to_key>(tx.vin[i]).k_image;
2092 
2093  this->buffer_send[offset+0] = amount>>56;
2094  this->buffer_send[offset+1] = amount>>48;
2095  this->buffer_send[offset+2] = amount>>40;
2096  this->buffer_send[offset+3] = amount>>32;
2097  this->buffer_send[offset+4] = amount>>24;
2098  this->buffer_send[offset+5] = amount>>16;
2099  this->buffer_send[offset+6] = amount>>8;
2100  this->buffer_send[offset+7] = amount>>0;
2101 
2102  offset += 8;
2103  //key_offset
2104  this->buffer_send[offset+0] = key_offset>>24;
2105  this->buffer_send[offset+1] = key_offset>>16;
2106  this->buffer_send[offset+2] = key_offset>>8;
2107  this->buffer_send[offset+3] = key_offset>>0;
2108  offset += 4;
2109  //k_image
2110  memmove(this->buffer_send+offset, k_image.data, 32);
2111  offset += 32;
2112 
2113  this->buffer_send[4] = offset-5;
2114  this->length_send = offset;
2115  this->exchange();
2116 
2117 #ifdef DEBUG_HWDEVICE
2118  hex_tx += boost::algorithm::hex(std::string(reinterpret_cast<char const*>(this->buffer_recv), this->length_recv));
2119 #endif
2120  }
2121 
2122  offset = set_command_header_noopt(INS_TX_PREFIX_OUTPUTS_SIZE);
2123  //vouts size
2124  size = tx.vout.size();
2125  this->buffer_send[offset+0] = size>>24;
2126  this->buffer_send[offset+1] = size>>16;
2127  this->buffer_send[offset+2] = size>>8;
2128  this->buffer_send[offset+3] = size>>0;
2129  offset += 4;
2130 
2131  this->buffer_send[4] = offset-5;
2132  this->length_send = offset;
2133  this->exchange();
2134 
2135 #ifdef DEBUG_HWDEVICE
2136  hex_tx += boost::algorithm::hex(std::string(reinterpret_cast<char const*>(this->buffer_recv), this->length_recv));
2137 #endif
2138 
2139  // count from #inputs + 1. Used for computing P=H(rA)G+B on device.
2140  // The output index is hashed in H so that we get unique stealth addresses when sending multiple outputs to the same person (same r,A,B)
2141  size_t output_index = tx.vin.size() + 1;
2142  for(size_t i = 0; i < tx.vout.size(); ++i) {
2143  offset = set_command_header_noopt(INS_TX_PREFIX_OUTPUTS);
2144 
2145  uint64_t amount = tx.vout[i].amount;
2146  crypto::public_key key = boost::get<cryptonote::txout_to_key>(tx.vout[i].target).key;
2147 
2148  //amount
2149  this->buffer_send[offset+0] = amount>>56;
2150  this->buffer_send[offset+1] = amount>>48;
2151  this->buffer_send[offset+2] = amount>>40;
2152  this->buffer_send[offset+3] = amount>>32;
2153  this->buffer_send[offset+4] = amount>>24;
2154  this->buffer_send[offset+5] = amount>>16;
2155  this->buffer_send[offset+6] = amount>>8;
2156  this->buffer_send[offset+7] = amount>>0;
2157  offset += 8;
2158  //key
2159  memmove(this->buffer_send+offset, key.data, 32);
2160  offset += 32;
2161 
2162  //output_index
2163  this->buffer_send[offset+0] = output_index>>24;
2164  this->buffer_send[offset+1] = output_index>>16;
2165  this->buffer_send[offset+2] = output_index>>8;
2166  this->buffer_send[offset+3] = output_index>>0;
2167  offset += 4;
2168 
2169  ++output_index;
2170 
2171  this->buffer_send[4] = offset-5;
2172  this->length_send = offset;
2173  this->exchange();
2174 
2175 #ifdef DEBUG_HWDEVICE
2176  hex_tx += boost::algorithm::hex(std::string(reinterpret_cast<char const*>(this->buffer_recv), this->length_recv));
2177 #endif
2178 
2179  }
2180 
2181  offset = set_command_header_noopt(INS_TX_PREFIX_EXTRA);
2182 
2183  //tx extra size
2184  size = tx.extra.size();
2185  this->buffer_send[offset+0] = size>>24;
2186  this->buffer_send[offset+1] = size>>16;
2187  this->buffer_send[offset+2] = size>>8;
2188  this->buffer_send[offset+3] = size>>0;
2189  offset += 4;
2190  //tx extra
2191  memmove(this->buffer_send+offset, tx.extra.data(), size);
2192  offset += size;
2193 
2194  this->buffer_send[4] = offset-5;
2195  this->length_send = offset;
2196  this->exchange();
2197 
2198  memmove(&tx_prefix_hash, &this->buffer_recv[0], 32);
2199 
2200 #ifdef DEBUG_HWDEVICE
2201  hex_tx += boost::algorithm::hex(std::string(reinterpret_cast<char const*>(this->buffer_recv), this->length_recv));
2202 #endif
2203 
2204  offset = set_command_header_noopt(INS_TX_PROMPT_FEE);
2205  this->buffer_send[4] = offset-5;
2206  this->length_send = offset;
2207  CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Fee denied on device.");
2208 
2209  offset = set_command_header_noopt(INS_TX_PROMPT_AMOUNT);
2210  this->buffer_send[4] = offset-5;
2211  this->length_send = offset;
2212  CHECK_AND_ASSERT_THROW_MES(this->exchange_wait_on_input() == 0, "Transaction denied on device.");
2213 
2214  return true;
2215  }
2216 
2217  bool device_ledger::hash_to_scalar(boost::shared_ptr<crypto::rs_comm> buf, size_t length, crypto::ec_scalar &res) {
2218  AUTO_LOCK_CMD();
2219 
2220  size_t pubs_count = (length - sizeof(crypto::rs_comm)) / sizeof(crypto::ec_point_pair);
2221 
2222 
2223  int offset = set_command_header_noopt(INS_HASH_TO_SCALAR_INIT);
2224  this->buffer_send[4] = offset-5;
2225  this->length_send = offset;
2226  this->exchange();
2227 
2228  for(size_t i = 0; i < pubs_count; ++i) {
2229  offset = set_command_header_noopt(INS_HASH_TO_SCALAR_BATCH);
2230 
2231  memmove(this->buffer_send+offset, buf->ab[i].a.data, 32);
2232  offset += 32;
2233  memmove(this->buffer_send+offset, buf->ab[i].b.data, 32);
2234  offset += 32;
2235 
2236  this->buffer_send[4] = offset-5;
2237  this->length_send = offset;
2238  this->exchange();
2239  }
2240 
2241  offset = set_command_header_noopt(INS_HASH_TO_SCALAR);
2242  this->buffer_send[4] = offset-5;
2243  this->length_send = offset;
2244  this->exchange();
2245 
2246  memmove(&res, &this->buffer_recv[0], 32);
2247 
2248  return true;
2249  }
2250 
2251  bool device_ledger::generate_ring_signature(const crypto::hash &prefix_hash, const crypto::key_image &image,
2252  const std::vector<const crypto::public_key *> &pubsvector,
2253  const crypto::secret_key &sec, std::size_t sec_index,
2254  crypto::signature *sig){
2255  //Todo: refactor function calls?
2256  const crypto::public_key *const *pubs = pubsvector.data();
2257  size_t pubs_count = pubsvector.size();
2258  size_t i;
2259  ge_p3 image_unp;
2260  ge_dsmp image_pre;
2261  crypto::ec_scalar sum, h, h2;
2262  crypto::secret_key q_s;
2263  boost::shared_ptr<crypto::rs_comm> buf(reinterpret_cast<crypto::rs_comm *>(malloc(crypto::rs_comm_size(pubs_count))), free);
2264  if (!buf)
2265  local_abort("malloc failure");
2266  assert(sec_index < pubs_count);
2267 #if !defined(NDEBUG)
2268  {
2269  for (i = 0; i < pubs_count; i++) {
2270  assert(check_key(*pubs[i]));
2271  }
2272  }
2273 #endif
2274  if (ge_frombytes_vartime(&image_unp, &image) != 0) {
2275  local_abort("invalid key image");
2276  }
2277  ge_dsm_precomp(image_pre, &image_unp);
2278  sc_0(&sum);
2279  buf->h = prefix_hash;
2280  for (i = 0; i < pubs_count; i++) {
2281  ge_p2 tmp2;
2282  ge_p3 tmp3;
2283  // Comments below use the same notation as the Cryptonote whitepaper.
2284  if (i == sec_index) {
2285  // Generate a random q_s
2286  // L_s = q_s*G;
2287  // Generate q_s onboard and perform L-transform. Pass q_s back encrypted.
2288  // If q_s were leaked in cleartext, someone could reverse engineer the output private key, and therefore
2289  // reverse engineer the overall private key. q_s being kept secret means we can 'close the loop' later on with
2290  // r_s = q_s -c_s*x where only r,c are known, for which there are l solutions (r'=q'-x') => privacy is maintained.
2291  crypto::public_key L_s;
2292  ge_p3 tmpimg;
2293  this->generate_keys(L_s, q_s);
2294  ge_frombytes_vartime(&tmp3, &L_s);
2295  // L_s in byte form
2296  ge_p3_tobytes(&buf->ab[i].a, &tmp3);
2297  // tmp3 now becomes H_p(P_s)
2298  hash_to_ec(*pubs[i], tmp3);
2299  // Onboard the device, this next step is equivalent to doing a key image calculation with q_s instead of x.
2300  // Complete R-transform : R_s = q_s * H_p(P_s)
2301  crypto::key_image R_s;
2302  this->generate_key_image(*pubs[i], q_s,R_s);
2303  ge_frombytes_vartime(&tmpimg, &R_s);
2304  // Key image is a p3 representation of an ed25519 point so convert to p2 first
2305  ge_p3_to_p2(&tmp2, &tmpimg);
2306  // R_s in byte form
2307  ge_tobytes(&buf->ab[i].b, &tmp2);
2308  } else {
2309  // Generate our random scalars w_i & q_i
2310  random_scalar(sig[i].c);
2311  random_scalar(sig[i].r);
2312  // Takes the byte form of P_i and converts to an ed25519 point.
2313  if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
2314  local_abort("invalid pubkey");
2315  }
2316  // Returns L_i = (q_i*G) + (w_i*P_i)
2317  ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
2318  // L_i in byte form
2319  ge_tobytes(&buf->ab[i].a, &tmp2);
2320  hash_to_ec(*pubs[i], tmp3);
2321  // R_i = (q_i * H_p(P_i)) + w_i*I
2322  ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre);
2323  // R_i in byte form
2324  ge_tobytes(&buf->ab[i].b, &tmp2);
2325  // Add c_i to the running sum of c_i's
2326  sc_add(&sum, &sum, &sig[i].c);
2327  }
2328  }
2329  // Keccak1600 Hash (H_s) of the buffer of all L&R, which is then converted to a 32 byte integer modulo l.
2330  hash_to_scalar(buf, crypto::rs_comm_size(pubs_count), h);
2331  // c_s = c-sum(c_i) where i != s
2332  sc_sub(&sig[sec_index].c, &h, &sum);
2333  // Close the loop: r_s = q_s - c_s*x
2334  // where x is the real output private key. This is the same x used to generate the key image.
2335  // Close the loop with r=q-cx (mulsub) onboard device to keep the secret nonce and output private key safe
2336  this->mulsub_eqx(sig[sec_index].r, sig[sec_index].c, unwrap(sec), unwrap(q_s));
2337  return true;
2338  }
2339 
2340  bool device_ledger::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){
2341  return true;// todo: 4.0.0.0
2342  }
2343 
2344 
2345  /* ---------------------------------------------------------- */
2346 
2347  static device_ledger *legder_device = NULL;
2348  void register_all(std::map<std::string, std::unique_ptr<device>> &registry) {
2349  if (!legder_device) {
2350  legder_device = new device_ledger();
2351  legder_device->set_name("Ledger");
2352  }
2353  registry.insert(std::make_pair("Ledger", std::unique_ptr<device>(legder_device)));
2354  }
2355 
2356  #else //WITH_DEVICE_LEDGER
2357 
2358  void register_all(std::map<std::string, std::unique_ptr<device>> &registry) {
2359  }
2360 
2361  #endif //WITH_DEVICE_LEDGER
2362 
2363  }
2364 }
2365 
const char * res
Definition: hmac_keccak.cpp:41
crypto::public_key pub
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res)
Definition: crypto.h:279
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
Definition: misc_log_ex.h:173
POD_CLASS ec_point
Definition: crypto.h:70
int crypto_verify_32(const unsigned char *, const unsigned char *)
void derive_secret_key(const key_derivation &derivation, std::size_t output_index, const secret_key &base, secret_key &derived_key)
Definition: crypto.h:282
#define MINIMAL_APP_VERSION_MAJOR
#define MINIMAL_APP_VERSION_MINOR
crypto::secret_key sec
::std::string string
Definition: gtest-port.h:1097
CXA_THROW_INFO_T void(* dest)(void *))
Definition: stack_trace.cpp:91
POD_CLASS key_derivation
Definition: crypto.h:98
void hash_to_ec(const crypto::public_key &key, crypto::ec_point &res)
Definition: crypto.cpp:48
void scalarmultKey(key &aP, const key &P, const key &a)
Definition: rctOps.cpp:368
void log_hexbuffer(const std::string &msg, const char *buff, size_t len)
Definition: log.cpp:45
#define ge_tobytes
Definition: ge.h:54
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *)
virtual bool set_mode(device_mode mode)
Definition: device.hpp:130
const char * key
Definition: hmac_keccak.cpp:39
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:82
void register_all(std::map< std::string, std::unique_ptr< device >> &registry)
void generate_input_signature(const hash prefix_hash, const uint32_t input_index, const secret_key sec_view, const secret_key sec_spend, signature &sig)
Definition: crypto.h:299
bool operator==(const some_test_data &a, const some_test_data &b)
#define VERSION_MAJOR(v)
unsigned char uint8_t
Definition: stdint.h:124
void ecdhEncode(ecdhTuple &unmasked, const key &sharedSec, bool v2)
Definition: rctOps.cpp:697
void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len)
Definition: log.cpp:38
const char * name
struct hash_func hashes[]
key genCommitmentMask(const key &sk)
Definition: rctOps.cpp:687
#define VERSION_MINOR(v)
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition: crypto.h:272
std::vector< uint8_t > extra
std::vector< key > keyV
Definition: rctTypes.h:88
#define MDEBUG(x)
Definition: misc_log_ex.h:76
Archiver & operator &(Archiver &ar, Student &s)
size_t rs_comm_size(size_t pubs_count)
Definition: crypto.cpp:511
const crypto::secret_key null_skey
Definition: crypto.cpp:73
Manages wallet operations. This is the most abstracted wallet class.
Definition: simplewallet.h:67
void generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional< public_key > &B, const public_key &D, const secret_key &r, signature &sig)
Definition: crypto.h:311
unsigned int uint32_t
Definition: stdint.h:126
cryptonote::simple_wallet sw
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 ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp)
void generate_ring_signature(const hash &prefix_hash, const key_image &image, const public_key *const *pubs, std::size_t pubs_count, const secret_key &sec, std::size_t sec_index, signature *sig)
Definition: crypto.h:327
#define ge_p3_to_p2
Definition: ge.h:60
device & get_device(const std::string &device_descriptor)
Definition: device.cpp:95
#define VERSION_MICRO(v)
std::vector< ctkey > ctkeyV
Definition: rctTypes.h:100
void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *)
#define MINIMAL_APP_VERSION_MICRO
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *)
unsigned __int64 uint64_t
Definition: stdint.h:136
const char *const ELECTRONEUM_VERSION
secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key &recovery_key=secret_key(), bool recover=false)
Definition: crypto.h:250
Definition: device.cpp:38
void sc_0(unsigned char *)
bool is_subaddress
POD_CLASS public_key
Definition: crypto.h:76
const char * buf
Definition: slow_memmem.cpp:74
void random_scalar(crypto::ec_scalar &res)
Definition: crypto.cpp:40
#define ge_p3_tobytes
Definition: ge.h:55
crypto::secret_key m_view_secret_key
Definition: account.h:45
void ecdhDecode(ecdhTuple &masked, const key &sharedSec, bool v2)
Definition: rctOps.cpp:712
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
account_public_address addr
void scalarmultBase(key &aG, const key &a)
Definition: rctOps.cpp:350
account_public_address m_account_address
Definition: account.h:43
void decrypt(const void *ciphertext, size_t length, const uint8_t *key, const uint8_t *iv, char *plaintext, size_t *plaintext_len)
Definition: protocol.cpp:120
ge_cached ge_dsmp[8]
Definition: crypto-ops.h:79
POD_CLASS signature
Definition: crypto.h:108
void get_transaction_prefix_hash(const transaction_prefix &tx, crypto::hash &h)
unsigned char bytes[32]
Definition: rctTypes.h:86
POD_CLASS hash8
Definition: hash.h:53
#define VERSION
Definition: db_lmdb.cpp:60
void hash_to_scalar(const void *data, std::size_t length, crypto::ec_scalar &res)
Definition: crypto.cpp:44
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s)
POD_CLASS key_image
Definition: crypto.h:102
void * memcpy(void *a, const void *b, size_t c)
Matcher< T > A()
crypto::secret_key m_spend_secret_key
Definition: account.h:44
bool derive_public_key(const key_derivation &derivation, std::size_t output_index, const public_key &base, public_key &derived_key)
Definition: crypto.h:275
bool check_key(const public_key &key)
Definition: crypto.h:256
T & unwrap(mlocked< T > &src)
Definition: mlocker.h:80
#define MINIMAL_APP_VERSION
connection< TProtocol > & operator=(const connection< TProtocol > &obj)
bool generate_output_ephemeral_keys(const size_t tx_version, const cryptonote::account_keys &sender_account_keys, const crypto::public_key &txkey_pub, const crypto::secret_key &tx_key, const cryptonote::tx_destination_entry &dst_entr, const boost::optional< cryptonote::account_public_address > &change_addr, const size_t output_index, const bool &need_additional_txkeys, const std::vector< crypto::secret_key > &additional_tx_keys, std::vector< crypto::public_key > &additional_tx_public_keys, std::vector< rct::key > &amount_keys, crypto::public_key &out_eph_public_key)
int ge_frombytes_vartime(ge_p3 *, const unsigned char *)
void log_message(const std::string &msg, const std::string &info)
Definition: log.cpp:51
POD_CLASS hash
Definition: hash.h:50
const char * address
Definition: multisig.cpp:37
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition: crypto.h:262
std::string to_string(t_connection_type type)
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
void * memmove(void *a, const void *b, size_t c)
void verbose(enum verbosity_value level, const char *format,...) ATTR_FORMAT(printf
int rows
Definition: crypto.h:86