Electroneum
Loading...
Searching...
No Matches
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
41namespace {
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
53namespace 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
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;
612 cryptonote::account_keys keys_x = hw::ledger::decrypt(keys);
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;
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()) {
702 D = keys.m_account_address.m_spend_public_key;
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
887 bool device_ledger::scalarmultBase(rct::key &aG, const rct::key &a) {
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
921 const crypto::secret_key a_x = hw::ledger::decrypt(a);
922 const crypto::secret_key b_x = hw::ledger::decrypt(b);
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
946 crypto::secret_key r_clear = hw::ledger::decrypt(r);
947 hw::ledger::check32("sc_secret_add", "r", r_x.data, r_clear.data);
948 #endif
949
950 return true;
951 }
952
953 crypto::secret_key device_ledger::generate_keys(crypto::public_key &pub, crypto::secret_key &sec, const crypto::secret_key& recovery_key, bool recover) {
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
1016 bool device_ledger::generate_key_derivation(const crypto::public_key &pub, const crypto::secret_key &sec, crypto::key_derivation &derivation) {
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
1086 bool device_ledger::derivation_to_scalar(const crypto::key_derivation &derivation, const size_t output_index, crypto::ec_scalar &res) {
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
1119 crypto::ec_scalar res_clear = hw::ledger::decrypt(res);
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
1211 bool device_ledger::secret_key_to_public_key(const crypto::secret_key &sec, crypto::public_key &pub) {
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
1601 rct::key device_ledger::genCommitmentMask(const rct::key &AKout) {
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
2048 bool device_ledger::get_transaction_prefix_hash(const cryptonote::transaction_prefix& tx, crypto::hash& tx_prefix_hash) {
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;
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.
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)
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
Archiver & operator&(Archiver &ar, Student &s)
virtual bool set_mode(device_mode mode)
Definition device.hpp:130
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp)
void sc_0(unsigned char *)
ge_cached ge_dsmp[8]
Definition crypto-ops.h:79
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s)
int ge_frombytes_vartime(ge_p3 *, const unsigned char *)
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *)
void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *)
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *)
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
int crypto_verify_32(const unsigned char *, const unsigned char *)
#define VERSION
Definition db_lmdb.cpp:60
#define VERSION_MAJOR(v)
#define VERSION_MINOR(v)
#define MINIMAL_APP_VERSION_MICRO
#define MINIMAL_APP_VERSION_MINOR
#define MINIMAL_APP_VERSION
#define MINIMAL_APP_VERSION_MAJOR
#define VERSION_MICRO(v)
bool operator==(expect< T > const &lhs, expect< U > const &rhs) noexcept(noexcept(lhs.equal(rhs)))
Definition expect.h:401
void * memmove(void *a, const void *b, size_t c)
void * memcpy(void *a, const void *b, size_t c)
const char * res
const char * key
void verbose(enum verbosity_value level, const char *format,...) ATTR_FORMAT(printf
#define MDEBUG(x)
Definition misc_log_ex.h:76
#define CHECK_AND_ASSERT_THROW_MES(expr, message)
POD_CLASS ec_point
Definition crypto.h:70
POD_CLASS signature
Definition crypto.h:108
const crypto::secret_key null_skey
Definition crypto.cpp:73
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
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
size_t rs_comm_size(size_t pubs_count)
Definition crypto.cpp:511
POD_CLASS hash8
Definition hash.h:53
POD_CLASS key_derivation
Definition crypto.h:101
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation)
Definition crypto.h:272
POD_CLASS public_key
Definition crypto.h:79
POD_CLASS key_image
Definition crypto.h:105
POD_CLASS ec_scalar
Definition crypto.h:74
bool secret_key_to_public_key(const secret_key &sec, public_key &pub)
Definition crypto.h:262
POD_CLASS hash
Definition hash.h:50
void register_all(std::map< std::string, std::unique_ptr< device > > &registry)
Definition device.cpp:38
void log_hexbuffer(const std::string &msg, const char *buff, size_t len)
Definition log.cpp:45
void log_message(const std::string &msg, const std::string &info)
Definition log.cpp:51
void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len)
Definition log.cpp:38
device & get_device(const std::string &device_descriptor)
Definition device.cpp:95
void scalarmultBase(key &aG, const key &a)
Definition rctOps.cpp:350
std::vector< key > keyV
Definition rctTypes.h:88
void scalarmultKey(key &aP, const key &P, const key &a)
Definition rctOps.cpp:368
std::vector< ctkey > ctkeyV
Definition rctTypes.h:100
@ RCTTypeSimple
Definition rctTypes.h:231
@ RCTTypeBulletproof2
Definition rctTypes.h:233
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124
#define ge_p3_tobytes
Definition ge.h:55
#define ge_p3_to_p2
Definition ge.h:60
#define ge_tobytes
Definition ge.h:54
cryptonote::simple_wallet sw
const char * buf
CXA_THROW_INFO_T void(* dest)(void *))
unsigned int uint32_t
Definition stdint.h:126
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
crypto::secret_key m_view_secret_key
Definition account.h:45
crypto::secret_key m_spend_secret_key
Definition account.h:44
account_public_address m_account_address
Definition account.h:43
crypto::secret_key sec
crypto::public_key pub
bool is_subaddress
account_public_address addr
unsigned char bytes[32]
Definition rctTypes.h:86
void hash_to_scalar(const void *data, std::size_t length, crypto::ec_scalar &res)
Definition crypto.cpp:44
void random_scalar(crypto::ec_scalar &res)
Definition crypto.cpp:40
void hash_to_ec(const crypto::public_key &key, crypto::ec_point &res)
Definition crypto.cpp:48
struct hash_func hashes[]
const char * address
Definition multisig.cpp:37
const char *const ELECTRONEUM_VERSION