2020-05-07 02:36:54 +00:00
// Copyright (c) 2017-2020, The Monero Project
2018-02-20 16:01:27 +00:00
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
2018-12-11 09:20:21 +00:00
# include "version.h"
2018-02-20 16:01:27 +00:00
# include "device_ledger.hpp"
# include "ringct/rctOps.h"
2018-03-05 07:16:30 +00:00
# include "cryptonote_basic/account.h"
# include "cryptonote_basic/subaddress_index.h"
2018-12-11 09:20:21 +00:00
# include "cryptonote_core/cryptonote_tx_utils.h"
2018-02-20 16:01:27 +00:00
2018-03-26 10:38:38 +00:00
# include <boost/thread/locks.hpp>
# include <boost/thread/lock_guard.hpp>
2018-02-20 16:01:27 +00:00
namespace hw {
namespace ledger {
# ifdef WITH_DEVICE_LEDGER
# undef MONERO_DEFAULT_LOG_CATEGORY
# define MONERO_DEFAULT_LOG_CATEGORY "device.ledger"
/* ===================================================================== */
/* === Debug ==== */
/* ===================================================================== */
2018-05-23 08:22:55 +00:00
2018-02-20 16:01:27 +00:00
void set_apdu_verbose ( bool verbose ) {
apdu_verbose = verbose ;
}
# define TRACKD MTRACE("hw")
2021-11-12 01:50:31 +00:00
# define ASSERT_SW(sw,ok,msk) CHECK_AND_ASSERT_THROW_MES(((sw)&(msk))==(ok), \
2020-02-07 14:20:38 +00:00
" Wrong Device Status: " < < " 0x " < < std : : hex < < ( sw ) < < " ( " < < Status : : to_string ( sw ) < < " ), " < < \
" EXPECTED 0x " < < std : : hex < < ( ok ) < < " ( " < < Status : : to_string ( ok ) < < " ), " < < \
2021-11-12 01:50:31 +00:00
" MASK 0x " < < std : : hex < < ( msk ) ) ;
2018-02-20 16:01:27 +00:00
# define ASSERT_T0(exp) CHECK_AND_ASSERT_THROW_MES(exp, "Protocol assert failure: "#exp ) ;
2018-04-09 14:07:11 +00:00
# define ASSERT_X(exp,msg) CHECK_AND_ASSERT_THROW_MES(exp, msg);
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
2018-03-26 10:55:48 +00:00
crypto : : secret_key dbg_viewkey ;
crypto : : secret_key dbg_spendkey ;
2018-02-20 16:01:27 +00:00
# endif
2020-02-07 14:20:38 +00:00
struct Status
{
unsigned int code ;
const char * string ;
constexpr operator unsigned int ( ) const
{
return this - > code ;
}
static const char * to_string ( unsigned int code ) ;
} ;
// Must be sorted in ascending order by the code
# define LEDGER_STATUS(status) {status, #status}
constexpr Status status_codes [ ] = {
2020-10-13 22:49:27 +00:00
LEDGER_STATUS ( SW_OK ) ,
2020-02-07 14:20:38 +00:00
LEDGER_STATUS ( SW_WRONG_LENGTH ) ,
2020-10-13 22:49:27 +00:00
LEDGER_STATUS ( SW_SECURITY_PIN_LOCKED ) ,
2020-02-07 14:20:38 +00:00
LEDGER_STATUS ( SW_SECURITY_LOAD_KEY ) ,
LEDGER_STATUS ( SW_SECURITY_COMMITMENT_CONTROL ) ,
LEDGER_STATUS ( SW_SECURITY_AMOUNT_CHAIN_CONTROL ) ,
LEDGER_STATUS ( SW_SECURITY_COMMITMENT_CHAIN_CONTROL ) ,
LEDGER_STATUS ( SW_SECURITY_OUTKEYS_CHAIN_CONTROL ) ,
LEDGER_STATUS ( SW_SECURITY_MAXOUTPUT_REACHED ) ,
2020-10-13 22:49:27 +00:00
LEDGER_STATUS ( SW_SECURITY_HMAC ) ,
LEDGER_STATUS ( SW_SECURITY_RANGE_VALUE ) ,
LEDGER_STATUS ( SW_SECURITY_INTERNAL ) ,
LEDGER_STATUS ( SW_SECURITY_MAX_SIGNATURE_REACHED ) ,
LEDGER_STATUS ( SW_SECURITY_PREFIX_HASH ) ,
LEDGER_STATUS ( SW_SECURITY_LOCKED ) ,
2020-02-07 14:20:38 +00:00
LEDGER_STATUS ( SW_COMMAND_NOT_ALLOWED ) ,
2020-10-13 22:49:27 +00:00
LEDGER_STATUS ( SW_SUBCOMMAND_NOT_ALLOWED ) ,
LEDGER_STATUS ( SW_DENY ) ,
LEDGER_STATUS ( SW_KEY_NOT_SET ) ,
2020-02-07 14:20:38 +00:00
LEDGER_STATUS ( SW_WRONG_DATA ) ,
2020-10-13 22:49:27 +00:00
LEDGER_STATUS ( SW_WRONG_DATA_RANGE ) ,
LEDGER_STATUS ( SW_IO_FULL ) ,
LEDGER_STATUS ( SW_CLIENT_NOT_SUPPORTED ) ,
2020-02-07 14:20:38 +00:00
LEDGER_STATUS ( SW_WRONG_P1P2 ) ,
LEDGER_STATUS ( SW_INS_NOT_SUPPORTED ) ,
2020-10-13 22:49:27 +00:00
LEDGER_STATUS ( SW_PROTOCOL_NOT_SUPPORTED ) ,
LEDGER_STATUS ( SW_UNKNOWN )
2020-02-07 14:20:38 +00:00
} ;
const char * Status : : to_string ( unsigned int code )
{
constexpr size_t status_codes_size = sizeof ( status_codes ) / sizeof ( status_codes [ 0 ] ) ;
constexpr const Status * status_codes_end = & status_codes [ status_codes_size ] ;
const Status * item = std : : lower_bound ( & status_codes [ 0 ] , status_codes_end , code ) ;
return ( item = = status_codes_end | | code < * item ) ? " UNKNOWN " : item - > string ;
}
2019-09-25 12:31:14 +00:00
/* ===================================================================== */
/* === hmacmap ==== */
/* ===================================================================== */
SecHMAC : : SecHMAC ( const uint8_t s [ 32 ] , const uint8_t h [ 32 ] ) {
memcpy ( this - > sec , s , 32 ) ;
memcpy ( this - > hmac , h , 32 ) ;
}
void HMACmap : : find_mac ( const uint8_t sec [ 32 ] , uint8_t hmac [ 32 ] ) {
size_t sz = hmacs . size ( ) ;
log_hexbuffer ( " find_mac: lookup for " , ( char * ) sec , 32 ) ;
for ( size_t i = 0 ; i < sz ; i + + ) {
log_hexbuffer ( " find_mac: - try " , ( char * ) hmacs [ i ] . sec , 32 ) ;
if ( memcmp ( sec , hmacs [ i ] . sec , 32 ) = = 0 ) {
memcpy ( hmac , hmacs [ i ] . hmac , 32 ) ;
log_hexbuffer ( " find_mac: - found " , ( char * ) hmacs [ i ] . hmac , 32 ) ;
return ;
}
}
throw std : : runtime_error ( " Protocol error: try to send untrusted secret " ) ;
}
void HMACmap : : add_mac ( const uint8_t sec [ 32 ] , const uint8_t hmac [ 32 ] ) {
log_hexbuffer ( " add_mac: sec " , ( char * ) sec , 32 ) ;
log_hexbuffer ( " add_mac: hmac " , ( char * ) hmac , 32 ) ;
hmacs . push_back ( SecHMAC ( sec , hmac ) ) ;
}
void HMACmap : : clear ( ) {
hmacs . clear ( ) ;
}
2018-02-20 16:01:27 +00:00
/* ===================================================================== */
/* === Keymap ==== */
/* ===================================================================== */
2018-12-11 09:20:21 +00:00
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 ) {
2018-02-20 16:01:27 +00:00
Aout = A ;
Bout = B ;
2018-03-05 13:46:15 +00:00
is_subaddress = is_subaddr ;
2018-12-11 09:20:21 +00:00
is_change_address = is_change ;
additional_key = need_additional_txkeys ;
2018-02-20 16:01:27 +00:00
index = real_output_index ;
Pout = P ;
AKout = AK ;
}
ABPkeys : : ABPkeys ( const ABPkeys & keys ) {
2018-03-05 13:46:15 +00:00
Aout = keys . Aout ;
Bout = keys . Bout ;
is_subaddress = keys . is_subaddress ;
2018-12-11 09:20:21 +00:00
is_change_address = keys . is_change_address ;
additional_key = keys . additional_key ;
2018-02-20 16:01:27 +00:00
index = keys . index ;
2018-03-05 13:46:15 +00:00
Pout = keys . Pout ;
2018-02-20 16:01:27 +00:00
AKout = keys . AKout ;
}
2019-06-08 15:58:33 +00:00
ABPkeys & ABPkeys : : operator = ( const ABPkeys & keys ) {
if ( & keys = = this )
return * this ;
Aout = keys . Aout ;
Bout = keys . Bout ;
is_subaddress = keys . is_subaddress ;
is_change_address = keys . is_change_address ;
additional_key = keys . additional_key ;
index = keys . index ;
Pout = keys . Pout ;
AKout = keys . AKout ;
return * this ;
}
2018-02-20 16:01:27 +00:00
bool Keymap : : find ( const rct : : key & P , ABPkeys & keys ) const {
size_t sz = ABP . size ( ) ;
for ( size_t i = 0 ; i < sz ; i + + ) {
if ( ABP [ i ] . Pout = = P ) {
keys = ABP [ i ] ;
return true ;
}
}
return false ;
}
void Keymap : : add ( const ABPkeys & keys ) {
ABP . push_back ( keys ) ;
}
void Keymap : : clear ( ) {
ABP . clear ( ) ;
}
# ifdef DEBUG_HWDEVICE
void Keymap : : log ( ) {
log_message ( " keymap " , " content " ) ;
size_t sz = ABP . size ( ) ;
for ( size_t i = 0 ; i < sz ; i + + ) {
log_message ( " keymap " , std : : to_string ( i ) ) ;
log_hexbuffer ( " Aout " , ( char * ) ABP [ i ] . Aout . bytes , 32 ) ;
log_hexbuffer ( " Bout " , ( char * ) ABP [ i ] . Bout . bytes , 32 ) ;
2018-03-05 13:46:15 +00:00
log_message ( " is_sub " , std : : to_string ( ABP [ i ] . is_subaddress ) ) ;
2018-02-20 16:01:27 +00:00
log_message ( " index " , std : : to_string ( ABP [ i ] . index ) ) ;
log_hexbuffer ( " Pout " , ( char * ) ABP [ i ] . Pout . bytes , 32 ) ;
}
}
# endif
/* ===================================================================== */
2018-03-26 10:55:48 +00:00
/* === Internal Helpers ==== */
/* ===================================================================== */
static bool is_fake_view_key ( const crypto : : secret_key & sec ) {
return sec = = crypto : : null_skey ;
}
2018-04-09 14:07:11 +00:00
bool operator = = ( const crypto : : key_derivation & d0 , const crypto : : key_derivation & d1 ) {
2018-06-13 17:23:06 +00:00
static_assert ( sizeof ( crypto : : key_derivation ) = = 32 , " key_derivation must be 32 bytes " ) ;
return ! crypto_verify_32 ( ( const unsigned char * ) & d0 , ( const unsigned char * ) & d1 ) ;
2018-04-09 14:07:11 +00:00
}
2018-03-26 10:55:48 +00:00
/* ===================================================================== */
/* === Device ==== */
2018-02-20 16:01:27 +00:00
/* ===================================================================== */
static int device_id = 0 ;
2020-08-28 09:59:02 +00:00
# define PROTOCOL_VERSION 4
2018-12-11 09:20:21 +00:00
2018-02-20 16:01:27 +00:00
# define INS_NONE 0x00
# define INS_RESET 0x02
# define INS_GET_KEY 0x20
2019-09-28 12:03:51 +00:00
# define INS_DISPLAY_ADDRESS 0x21
2018-02-20 16:01:27 +00:00
# define INS_PUT_KEY 0x22
# define INS_GET_CHACHA8_PREKEY 0x24
# define INS_VERIFY_KEY 0x26
2019-09-28 12:03:51 +00:00
# define INS_MANAGE_SEEDWORDS 0x28
2018-02-20 16:01:27 +00:00
# define INS_SECRET_KEY_TO_PUBLIC_KEY 0x30
# define INS_GEN_KEY_DERIVATION 0x32
# define INS_DERIVATION_TO_SCALAR 0x34
# define INS_DERIVE_PUBLIC_KEY 0x36
# define INS_DERIVE_SECRET_KEY 0x38
# define INS_GEN_KEY_IMAGE 0x3A
# define INS_SECRET_KEY_ADD 0x3C
# define INS_SECRET_KEY_SUB 0x3E
# define INS_GENERATE_KEYPAIR 0x40
# define INS_SECRET_SCAL_MUL_KEY 0x42
# define INS_SECRET_SCAL_MUL_BASE 0x44
# define INS_DERIVE_SUBADDRESS_PUBLIC_KEY 0x46
# define INS_GET_SUBADDRESS 0x48
# define INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY 0x4A
# define INS_GET_SUBADDRESS_SECRET_KEY 0x4C
# define INS_OPEN_TX 0x70
# define INS_SET_SIGNATURE_MODE 0x72
# define INS_GET_ADDITIONAL_KEY 0x74
# define INS_STEALTH 0x76
2018-12-11 09:20:21 +00:00
# define INS_GEN_COMMITMENT_MASK 0x77
2018-02-20 16:01:27 +00:00
# define INS_BLIND 0x78
# define INS_UNBLIND 0x7A
2018-12-11 09:20:21 +00:00
# define INS_GEN_TXOUT_KEYS 0x7B
2020-04-03 20:56:55 +00:00
# define INS_PREFIX_HASH 0x7D
2018-02-20 16:01:27 +00:00
# define INS_VALIDATE 0x7C
# define INS_MLSAG 0x7E
2020-03-31 15:11:51 +00:00
# define INS_CLSAG 0x7F
2018-02-20 16:01:27 +00:00
# define INS_CLOSE_TX 0x80
2019-03-21 16:22:43 +00:00
# define INS_GET_TX_PROOF 0xA0
2018-02-20 16:01:27 +00:00
# define INS_GET_RESPONSE 0xc0
2019-01-09 08:20:53 +00:00
device_ledger : : device_ledger ( ) : hw_device ( 0x0101 , 0x05 , 64 , 2000 ) {
2018-02-20 16:01:27 +00:00
this - > id = device_id + + ;
this - > reset_buffer ( ) ;
2018-03-26 10:55:48 +00:00
this - > mode = NONE ;
this - > has_view_key = false ;
2019-09-25 12:31:14 +00:00
this - > tx_in_progress = false ;
2018-02-20 16:01:27 +00:00
MDEBUG ( " Device " < < this - > id < < " Created " ) ;
}
device_ledger : : ~ device_ledger ( ) {
this - > release ( ) ;
MDEBUG ( " Device " < < this - > id < < " Destroyed " ) ;
}
2018-03-26 10:38:38 +00:00
/* ======================================================================= */
/* LOCKER */
/* ======================================================================= */
//automatic lock one more level on device ensuring the current thread is allowed to use it
# define AUTO_LOCK_CMD() \
/* lock both mutexes without deadlock*/ \
boost : : lock ( device_locker , command_locker ) ; \
/* make sure both already-locked mutexes are unlocked at the end of scope */ \
boost : : lock_guard < boost : : recursive_mutex > lock1 ( device_locker , boost : : adopt_lock ) ; \
boost : : lock_guard < boost : : mutex > lock2 ( command_locker , boost : : adopt_lock )
//lock the device for a long sequence
void device_ledger : : lock ( void ) {
MDEBUG ( " Ask for LOCKING for device " < < this - > name < < " in thread " ) ;
device_locker . lock ( ) ;
MDEBUG ( " Device " < < this - > name < < " LOCKed " ) ;
}
//lock the device for a long sequence
bool device_ledger : : try_lock ( void ) {
MDEBUG ( " Ask for LOCKING(try) for device " < < this - > name < < " in thread " ) ;
bool r = device_locker . try_lock ( ) ;
if ( r ) {
MDEBUG ( " Device " < < this - > name < < " LOCKed(try) " ) ;
} else {
MDEBUG ( " Device " < < this - > name < < " not LOCKed(try) " ) ;
}
return r ;
}
//lock the device for a long sequence
void device_ledger : : unlock ( void ) {
try {
MDEBUG ( " Ask for UNLOCKING for device " < < this - > name < < " in thread " ) ;
} catch ( . . . ) {
}
device_locker . unlock ( ) ;
MDEBUG ( " Device " < < this - > name < < " UNLOCKed " ) ;
}
2018-02-20 16:01:27 +00:00
2018-08-01 07:24:53 +00:00
2018-02-20 16:01:27 +00:00
/* ======================================================================= */
2018-08-01 07:24:53 +00:00
/* IO */
2018-02-20 16:01:27 +00:00
/* ======================================================================= */
2018-08-01 07:24:53 +00:00
2019-01-09 08:20:53 +00:00
# define IO_SW_DENY 0x6982
# define IO_SECRET_KEY 0x02
2018-08-01 07:24:53 +00:00
void device_ledger : : logCMD ( ) {
if ( apdu_verbose ) {
char strbuffer [ 1024 ] ;
snprintf ( strbuffer , sizeof ( strbuffer ) , " %.02x %.02x %.02x %.02x %.02x " ,
this - > buffer_send [ 0 ] ,
this - > buffer_send [ 1 ] ,
this - > buffer_send [ 2 ] ,
this - > buffer_send [ 3 ] ,
this - > buffer_send [ 4 ]
) ;
const size_t len = strlen ( strbuffer ) ;
buffer_to_str ( strbuffer + len , sizeof ( strbuffer ) - len , ( char * ) ( this - > buffer_send + 5 ) , this - > length_send - 5 ) ;
MDEBUG ( " CMD : " < < strbuffer ) ;
}
}
void device_ledger : : logRESP ( ) {
if ( apdu_verbose ) {
char strbuffer [ 1024 ] ;
snprintf ( strbuffer , sizeof ( strbuffer ) , " %.04x " , this - > sw ) ;
const size_t len = strlen ( strbuffer ) ;
buffer_to_str ( strbuffer + len , sizeof ( strbuffer ) - len , ( char * ) ( this - > buffer_recv ) , this - > length_recv ) ;
MDEBUG ( " RESP : " < < strbuffer ) ;
}
}
int device_ledger : : set_command_header ( unsigned char ins , unsigned char p1 , unsigned char p2 ) {
2018-06-20 09:40:09 +00:00
reset_buffer ( ) ;
2018-12-11 09:20:21 +00:00
this - > buffer_send [ 0 ] = PROTOCOL_VERSION ;
2018-06-20 09:40:09 +00:00
this - > buffer_send [ 1 ] = ins ;
this - > buffer_send [ 2 ] = p1 ;
this - > buffer_send [ 3 ] = p2 ;
this - > buffer_send [ 4 ] = 0x00 ;
return 5 ;
}
2018-02-20 16:01:27 +00:00
2018-08-01 07:24:53 +00:00
int device_ledger : : set_command_header_noopt ( unsigned char ins , unsigned char p1 , unsigned char p2 ) {
2018-06-20 09:40:09 +00:00
int offset = set_command_header ( ins , p1 , p2 ) ;
//options
this - > buffer_send [ offset + + ] = 0 ;
this - > buffer_send [ 4 ] = offset - 5 ;
return offset ;
}
2018-08-01 07:24:53 +00:00
void device_ledger : : send_simple ( unsigned char ins , unsigned char p1 ) {
2018-06-20 09:40:09 +00:00
this - > length_send = set_command_header_noopt ( ins , p1 ) ;
2019-01-09 08:20:53 +00:00
if ( ins = = INS_GET_KEY & & p1 = = IO_SECRET_KEY ) {
// export view key user input
this - > exchange_wait_on_input ( ) ;
} else {
this - > exchange ( ) ;
}
2018-06-20 09:40:09 +00:00
}
2019-09-25 12:31:14 +00:00
void device_ledger : : send_secret ( const unsigned char sec [ 32 ] , int & offset ) {
MDEBUG ( " send_secret: " < < this - > tx_in_progress ) ;
2019-10-25 13:13:23 +00:00
ASSERT_X ( offset + 32 < = BUFFER_SEND_SIZE , " send_secret: out of bounds write (secret) " ) ;
2019-09-25 12:31:14 +00:00
memmove ( this - > buffer_send + offset , sec , 32 ) ;
offset + = 32 ;
if ( this - > tx_in_progress ) {
2019-10-25 13:13:23 +00:00
ASSERT_X ( offset + 32 < = BUFFER_SEND_SIZE , " send_secret: out of bounds write (mac) " ) ;
2019-09-25 12:31:14 +00:00
this - > hmac_map . find_mac ( ( uint8_t * ) sec , this - > buffer_send + offset ) ;
offset + = 32 ;
}
}
void device_ledger : : receive_secret ( unsigned char sec [ 32 ] , int & offset ) {
MDEBUG ( " receive_secret: " < < this - > tx_in_progress ) ;
2019-10-25 13:13:23 +00:00
ASSERT_X ( offset + 32 < = BUFFER_RECV_SIZE , " receive_secret: out of bounds read (secret) " ) ;
2019-09-25 12:31:14 +00:00
memmove ( sec , this - > buffer_recv + offset , 32 ) ;
offset + = 32 ;
if ( this - > tx_in_progress ) {
2019-10-25 13:13:23 +00:00
ASSERT_X ( offset + 32 < = BUFFER_RECV_SIZE , " receive_secret: out of bounds read (mac) " ) ;
2019-09-25 12:31:14 +00:00
this - > hmac_map . add_mac ( ( uint8_t * ) sec , this - > buffer_recv + offset ) ;
offset + = 32 ;
}
}
2018-06-20 09:40:09 +00:00
bool device_ledger : : reset ( ) {
2019-03-07 22:34:53 +00:00
reset_buffer ( ) ;
int offset = set_command_header_noopt ( INS_RESET ) ;
2019-07-03 13:49:59 +00:00
const size_t verlen = strlen ( MONERO_VERSION ) ;
ASSERT_X ( offset + verlen < = BUFFER_SEND_SIZE , " MONERO_VERSION is too long " )
memmove ( this - > buffer_send + offset , MONERO_VERSION , verlen ) ;
2019-03-07 22:34:53 +00:00
offset + = strlen ( MONERO_VERSION ) ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
ASSERT_X ( this - > length_recv > = 3 , " Communication error, less than three bytes received. Check your application version. " ) ;
return true ;
2018-02-20 16:01:27 +00:00
}
unsigned int device_ledger : : exchange ( unsigned int ok , unsigned int mask ) {
logCMD ( ) ;
2019-01-09 08:20:53 +00:00
this - > length_recv = hw_device . exchange ( this - > buffer_send , this - > length_send , this - > buffer_recv , BUFFER_SEND_SIZE , false ) ;
2018-08-01 07:24:53 +00:00
ASSERT_X ( this - > length_recv > = 2 , " Communication error, less than tow bytes received " ) ;
this - > length_recv - = 2 ;
this - > sw = ( this - > buffer_recv [ length_recv ] < < 8 ) | this - > buffer_recv [ length_recv + 1 ] ;
2018-12-11 09:20:21 +00:00
logRESP ( ) ;
2021-11-02 23:02:59 +00:00
MDEBUG ( " Device " < < this - > id < < " exchange: sw: " < < this - > sw < < " expected: " < < ok ) ;
ASSERT_X ( sw ! = SW_CLIENT_NOT_SUPPORTED , " Monero Ledger App doesn't support current monero version. Try to update the Monero Ledger App, at least " < < MINIMAL_APP_VERSION_MAJOR < < " . " < < MINIMAL_APP_VERSION_MINOR < < " . " < < MINIMAL_APP_VERSION_MICRO < < " is required. " ) ;
ASSERT_X ( sw ! = SW_PROTOCOL_NOT_SUPPORTED , " Make sure no other program is communicating with the Ledger. " ) ;
2021-11-12 01:50:31 +00:00
ASSERT_SW ( this - > sw , ok , mask ) ;
2018-08-01 07:24:53 +00:00
return this - > sw ;
2018-02-20 16:01:27 +00:00
}
2019-01-09 08:20:53 +00:00
unsigned int device_ledger : : exchange_wait_on_input ( unsigned int ok , unsigned int mask ) {
logCMD ( ) ;
unsigned int deny = 0 ;
this - > length_recv = hw_device . exchange ( this - > buffer_send , this - > length_send , this - > buffer_recv , BUFFER_SEND_SIZE , true ) ;
ASSERT_X ( this - > length_recv > = 2 , " Communication error, less than two bytes received " ) ;
this - > length_recv - = 2 ;
this - > sw = ( this - > buffer_recv [ length_recv ] < < 8 ) | this - > buffer_recv [ length_recv + 1 ] ;
if ( this - > sw = = IO_SW_DENY ) {
// cancel on device
deny = 1 ;
} else {
2021-11-12 01:50:31 +00:00
ASSERT_SW ( this - > sw , ok , mask ) ;
2019-01-09 08:20:53 +00:00
}
logRESP ( ) ;
return deny ;
}
2018-02-20 16:01:27 +00:00
void device_ledger : : reset_buffer ( ) {
this - > length_send = 0 ;
memset ( this - > buffer_send , 0 , BUFFER_SEND_SIZE ) ;
this - > length_recv = 0 ;
memset ( this - > buffer_recv , 0 , BUFFER_RECV_SIZE ) ;
}
/* ======================================================================= */
/* SETUP/TEARDOWN */
/* ======================================================================= */
bool device_ledger : : set_name ( const std : : string & name ) {
this - > name = name ;
return true ;
}
const std : : string device_ledger : : get_name ( ) const {
2019-01-09 04:32:04 +00:00
if ( ! this - > connected ( ) ) {
2018-02-20 16:01:27 +00:00
return std : : string ( " <disconnected: " ) . append ( this - > name ) . append ( " > " ) ;
}
2018-08-01 07:24:53 +00:00
return this - > name ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : init ( void ) {
2018-03-05 13:46:15 +00:00
this - > controle_device = & hw : : get_device ( " default " ) ;
2018-02-20 16:01:27 +00:00
this - > release ( ) ;
2018-08-01 07:24:53 +00:00
hw_device . init ( ) ;
MDEBUG ( " Device " < < this - > id < < " HIDUSB inited " ) ;
2018-02-20 16:01:27 +00:00
return true ;
}
2019-03-28 16:14:24 +00:00
static const std : : vector < hw : : io : : hid_conn_params > known_devices {
{ 0x2c97 , 0x0001 , 0 , 0xffa0 } ,
{ 0x2c97 , 0x0004 , 0 , 0xffa0 } ,
} ;
2018-02-20 16:01:27 +00:00
bool device_ledger : : connect ( void ) {
this - > disconnect ( ) ;
2019-03-28 16:14:24 +00:00
hw_device . connect ( known_devices ) ;
2018-02-20 16:01:27 +00:00
this - > reset ( ) ;
# ifdef DEBUG_HWDEVICE
cryptonote : : account_public_address pubkey ;
this - > get_public_address ( pubkey ) ;
2019-10-01 13:52:47 +00:00
# endif
2018-02-20 16:01:27 +00:00
crypto : : secret_key vkey ;
crypto : : secret_key skey ;
this - > get_secret_keys ( vkey , skey ) ;
2018-08-01 07:24:53 +00:00
return true ;
}
bool device_ledger : : connected ( void ) const {
return hw_device . connected ( ) ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : disconnect ( ) {
2018-08-01 07:24:53 +00:00
hw_device . disconnect ( ) ;
return true ;
}
bool device_ledger : : release ( ) {
this - > disconnect ( ) ;
hw_device . release ( ) ;
2018-02-20 16:01:27 +00:00
return true ;
}
2018-03-26 10:55:48 +00:00
bool device_ledger : : set_mode ( device_mode mode ) {
AUTO_LOCK_CMD ( ) ;
int offset ;
switch ( mode ) {
case TRANSACTION_CREATE_REAL :
case TRANSACTION_CREATE_FAKE :
2018-06-20 09:40:09 +00:00
offset = set_command_header_noopt ( INS_SET_SIGNATURE_MODE , 1 ) ;
2018-03-26 10:55:48 +00:00
//account
this - > buffer_send [ offset ] = mode ;
offset + = 1 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
this - > mode = mode ;
break ;
case TRANSACTION_PARSE :
case NONE :
this - > mode = mode ;
break ;
default :
CHECK_AND_ASSERT_THROW_MES ( false , " device_ledger::set_mode(unsigned int mode): invalid mode: " < < mode ) ;
}
MDEBUG ( " Switch to mode: " < < mode ) ;
2018-10-19 11:15:31 +00:00
return device : : set_mode ( mode ) ;
2018-03-26 10:55:48 +00:00
}
2018-02-20 16:01:27 +00:00
/* ======================================================================= */
/* WALLET & ADDRESS */
/* ======================================================================= */
bool device_ledger : : get_public_address ( cryptonote : : account_public_address & pubkey ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
2018-06-20 09:40:09 +00:00
send_simple ( INS_GET_KEY , 1 ) ;
2018-02-20 16:01:27 +00:00
memmove ( pubkey . m_view_public_key . data , this - > buffer_recv , 32 ) ;
memmove ( pubkey . m_spend_public_key . data , this - > buffer_recv + 32 , 32 ) ;
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
2018-03-26 10:55:48 +00:00
bool device_ledger : : get_secret_keys ( crypto : : secret_key & vkey , crypto : : secret_key & skey ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-03-05 13:46:15 +00:00
2018-03-26 10:55:48 +00:00
//secret key are represented as fake key on the wallet side
memset ( vkey . data , 0x00 , 32 ) ;
memset ( skey . data , 0xFF , 32 ) ;
2018-02-20 16:01:27 +00:00
//spcialkey, normal conf handled in decrypt
2018-06-20 09:40:09 +00:00
send_simple ( INS_GET_KEY , 0x02 ) ;
2018-02-20 16:01:27 +00:00
2018-03-26 10:55:48 +00:00
//View key is retrievied, if allowed, to speed up blockchain parsing
memmove ( this - > viewkey . data , this - > buffer_recv + 0 , 32 ) ;
if ( is_fake_view_key ( this - > viewkey ) ) {
MDEBUG ( " Have Not view key " ) ;
this - > has_view_key = false ;
} else {
MDEBUG ( " Have view key " ) ;
this - > has_view_key = true ;
}
# ifdef DEBUG_HWDEVICE
2019-10-01 15:28:23 +00:00
send_simple ( INS_GET_KEY , 0x04 ) ;
2018-03-26 10:55:48 +00:00
memmove ( dbg_viewkey . data , this - > buffer_recv + 0 , 32 ) ;
memmove ( dbg_spendkey . data , this - > buffer_recv + 32 , 32 ) ;
# endif
2018-03-26 10:38:38 +00:00
2018-03-26 10:55:48 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
2018-07-06 06:42:08 +00:00
bool device_ledger : : generate_chacha_key ( const cryptonote : : account_keys & keys , crypto : : chacha_key & key , uint64_t kdf_rounds ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
crypto : : chacha_key key_x ;
2018-03-05 13:46:15 +00:00
cryptonote : : account_keys keys_x = hw : : ledger : : decrypt ( keys ) ;
2018-07-06 06:42:08 +00:00
this - > controle_device - > generate_chacha_key ( keys_x , key_x , kdf_rounds ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
send_simple ( INS_GET_CHACHA8_PREKEY ) ;
2018-02-20 16:01:27 +00:00
char prekey [ 200 ] ;
memmove ( prekey , & this - > buffer_recv [ 0 ] , 200 ) ;
2018-07-06 06:42:08 +00:00
crypto : : generate_chacha_key_prehashed ( & prekey [ 0 ] , sizeof ( prekey ) , key , kdf_rounds ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
2018-03-05 09:24:11 +00:00
hw : : ledger : : check32 ( " generate_chacha_key_prehashed " , " key " , ( char * ) key_x . data ( ) , ( char * ) key . data ( ) ) ;
2018-02-20 16:01:27 +00:00
# endif
return true ;
}
2019-09-28 12:03:51 +00:00
void device_ledger : : display_address ( const cryptonote : : subaddress_index & index , const boost : : optional < crypto : : hash8 > & payment_id ) {
AUTO_LOCK_CMD ( ) ;
int offset = set_command_header_noopt ( INS_DISPLAY_ADDRESS , payment_id ? 1 : 0 ) ;
//index
memmove ( this - > buffer_send + offset , & index , sizeof ( cryptonote : : subaddress_index ) ) ;
offset + = 8 ;
//payment ID
if ( payment_id ) {
memmove ( this - > buffer_send + offset , ( * payment_id ) . data , 8 ) ;
} else {
memset ( this - > buffer_send + offset , 0 , 8 ) ;
}
offset + = 8 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
CHECK_AND_ASSERT_THROW_MES ( this - > exchange_wait_on_input ( ) = = 0 , " Timeout/Error on display address. " ) ;
}
2018-02-20 16:01:27 +00:00
/* ======================================================================= */
/* SUB ADDRESS */
/* ======================================================================= */
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 ) {
# ifdef DEBUG_HWDEVICE
const crypto : : public_key pub_x = pub ;
2018-03-26 10:55:48 +00:00
crypto : : key_derivation derivation_x ;
if ( ( this - > mode = = TRANSACTION_PARSE ) & & has_view_key ) {
derivation_x = derivation ;
} else {
derivation_x = hw : : ledger : : decrypt ( derivation ) ;
}
2018-02-20 16:01:27 +00:00
const std : : size_t output_index_x = output_index ;
crypto : : public_key derived_pub_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " derive_subaddress_public_key: [[IN]] pub " , pub_x . data , 32 ) ;
log_hexbuffer ( " derive_subaddress_public_key: [[IN]] derivation " , derivation_x . data , 32 ) ;
log_message ( " derive_subaddress_public_key: [[IN]] index " , std : : to_string ( ( int ) output_index_x ) ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > derive_subaddress_public_key ( pub_x , derivation_x , output_index_x , derived_pub_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " derive_subaddress_public_key: [[OUT]] derived_pub " , derived_pub_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-03-26 10:55:48 +00:00
if ( ( this - > mode = = TRANSACTION_PARSE ) & & has_view_key ) {
//If we are in TRANSACTION_PARSE, the given derivation has been retrieved uncrypted (wihtout the help
//of the device), so continue that way.
MDEBUG ( " derive_subaddress_public_key : PARSE mode with known viewkey " ) ;
crypto : : derive_subaddress_public_key ( pub , derivation , output_index , derived_pub ) ;
} else {
2021-06-04 15:41:42 +00:00
AUTO_LOCK_CMD ( ) ;
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_DERIVE_SUBADDRESS_PUBLIC_KEY ) ;
2018-02-20 16:01:27 +00:00
//pub
memmove ( this - > buffer_send + offset , pub . data , 32 ) ;
offset + = 32 ;
//derivation
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) derivation . data , offset ) ;
2018-02-20 16:01:27 +00:00
//index
this - > buffer_send [ offset + 0 ] = output_index > > 24 ;
this - > buffer_send [ offset + 1 ] = output_index > > 16 ;
this - > buffer_send [ offset + 2 ] = output_index > > 8 ;
this - > buffer_send [ offset + 3 ] = output_index > > 0 ;
offset + = 4 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
//pub key
memmove ( derived_pub . data , & this - > buffer_recv [ 0 ] , 32 ) ;
2018-03-26 10:55:48 +00:00
}
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " derive_subaddress_public_key " , " derived_pub " , derived_pub_x . data , derived_pub . data ) ;
# endif
2018-02-20 16:01:27 +00:00
return true ;
}
2018-03-05 05:24:48 +00:00
crypto : : public_key device_ledger : : get_subaddress_spend_public_key ( const cryptonote : : account_keys & keys , const cryptonote : : subaddress_index & index ) {
2021-06-04 13:02:06 +00:00
if ( has_view_key ) {
cryptonote : : account_keys keys_ { keys } ;
keys_ . m_view_secret_key = this - > viewkey ;
return this - > controle_device - > get_subaddress_spend_public_key ( keys_ , index ) ;
}
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
crypto : : public_key D ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const cryptonote : : account_keys keys_x = hw : : ledger : : decrypt ( keys ) ;
const cryptonote : : subaddress_index index_x = index ;
crypto : : public_key D_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " get_subaddress_spend_public_key: [[IN]] keys.m_view_secret_key " , keys_x . m_view_secret_key . data , 32 ) ;
log_hexbuffer ( " get_subaddress_spend_public_key: [[IN]] keys.m_spend_secret_key " , keys_x . m_spend_secret_key . data , 32 ) ;
log_message ( " get_subaddress_spend_public_key: [[IN]] index " , std : : to_string ( index_x . major ) + " . " + std : : to_string ( index_x . minor ) ) ;
2018-03-26 10:38:38 +00:00
D_x = this - > controle_device - > get_subaddress_spend_public_key ( keys_x , index_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " get_subaddress_spend_public_key: [[OUT]] derivation " , D_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
if ( index . is_zero ( ) ) {
D = keys . m_account_address . m_spend_public_key ;
} else {
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_GET_SUBADDRESS_SPEND_PUBLIC_KEY ) ;
2018-02-20 16:01:27 +00:00
//index
static_assert ( sizeof ( cryptonote : : subaddress_index ) = = 8 , " cryptonote::subaddress_index shall be 8 bytes length " ) ;
memmove ( this - > buffer_send + offset , & index , sizeof ( cryptonote : : subaddress_index ) ) ;
offset + = 8 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
memmove ( D . data , & this - > buffer_recv [ 0 ] , 32 ) ;
}
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " get_subaddress_spend_public_key " , " D " , D_x . data , D . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return D ;
2018-02-20 16:01:27 +00:00
}
2018-03-05 05:24:48 +00:00
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 ) {
std : : vector < crypto : : public_key > pkeys ;
2018-02-20 16:01:27 +00:00
cryptonote : : subaddress_index index = { account , begin } ;
crypto : : public_key D ;
for ( uint32_t idx = begin ; idx < end ; + + idx ) {
index . minor = idx ;
2018-03-05 05:24:48 +00:00
D = this - > get_subaddress_spend_public_key ( keys , index ) ;
2018-02-20 16:01:27 +00:00
pkeys . push_back ( D ) ;
}
2018-03-05 05:24:48 +00:00
return pkeys ;
2018-02-20 16:01:27 +00:00
}
2018-03-05 05:24:48 +00:00
cryptonote : : account_public_address device_ledger : : get_subaddress ( const cryptonote : : account_keys & keys , const cryptonote : : subaddress_index & index ) {
2021-06-04 13:02:06 +00:00
if ( has_view_key ) {
cryptonote : : account_keys keys_ { keys } ;
keys_ . m_view_secret_key = this - > viewkey ;
return this - > controle_device - > get_subaddress ( keys_ , index ) ;
}
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
cryptonote : : account_public_address address ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const cryptonote : : account_keys keys_x = hw : : ledger : : decrypt ( keys ) ;
const cryptonote : : subaddress_index index_x = index ;
cryptonote : : account_public_address address_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " get_subaddress: [[IN]] keys.m_view_secret_key " , keys_x . m_view_secret_key . data , 32 ) ;
log_hexbuffer ( " get_subaddress: [[IN]] keys.m_view_public_key " , keys_x . m_account_address . m_view_public_key . data , 32 ) ;
log_hexbuffer ( " get_subaddress: [[IN]] keys.m_view_secret_key " , keys_x . m_view_secret_key . data , 32 ) ;
log_hexbuffer ( " get_subaddress: [[IN]] keys.m_spend_public_key " , keys_x . m_account_address . m_spend_public_key . data , 32 ) ;
log_message ( " get_subaddress: [[IN]] index " , std : : to_string ( index_x . major ) + " . " + std : : to_string ( index_x . minor ) ) ;
2018-03-26 10:38:38 +00:00
address_x = this - > controle_device - > get_subaddress ( keys_x , index_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " get_subaddress: [[OUT]] keys.m_view_public_key " , address_x . m_view_public_key . data , 32 ) ;
log_hexbuffer ( " get_subaddress: [[OUT]] keys.m_spend_public_key " , address_x . m_spend_public_key . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
if ( index . is_zero ( ) ) {
address = keys . m_account_address ;
} else {
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_GET_SUBADDRESS ) ;
2018-02-20 16:01:27 +00:00
//index
static_assert ( sizeof ( cryptonote : : subaddress_index ) = = 8 , " cryptonote::subaddress_index shall be 8 bytes length " ) ;
memmove ( this - > buffer_send + offset , & index , sizeof ( cryptonote : : subaddress_index ) ) ;
offset + = 8 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
memmove ( address . m_view_public_key . data , & this - > buffer_recv [ 0 ] , 32 ) ;
memmove ( address . m_spend_public_key . data , & this - > buffer_recv [ 32 ] , 32 ) ;
}
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " get_subaddress " , " address.m_view_public_key.data " , address_x . m_view_public_key . data , address . m_view_public_key . data ) ;
hw : : ledger : : check32 ( " get_subaddress " , " address.m_spend_public_key.data " , address_x . m_spend_public_key . data , address . m_spend_public_key . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return address ;
2018-02-20 16:01:27 +00:00
}
2018-03-05 05:24:48 +00:00
crypto : : secret_key device_ledger : : get_subaddress_secret_key ( const crypto : : secret_key & sec , const cryptonote : : subaddress_index & index ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
crypto : : secret_key sub_sec ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : secret_key sec_x = hw : : ledger : : decrypt ( sec ) ;
const cryptonote : : subaddress_index index_x = index ;
crypto : : secret_key sub_sec_x ;
2019-02-06 14:05:06 +00:00
log_message ( " get_subaddress_secret_key: [[IN]] index " , std : : to_string ( index . major ) + " . " + std : : to_string ( index . minor ) ) ;
log_hexbuffer ( " get_subaddress_secret_key: [[IN]] sec " , sec_x . data , 32 ) ;
2018-03-26 10:38:38 +00:00
sub_sec_x = this - > controle_device - > get_subaddress_secret_key ( sec_x , index_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " get_subaddress_secret_key: [[OUT]] sub_sec " , sub_sec_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_GET_SUBADDRESS_SECRET_KEY ) ;
2018-02-20 16:01:27 +00:00
//sec
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) sec . data , offset ) ;
2018-02-20 16:01:27 +00:00
//index
static_assert ( sizeof ( cryptonote : : subaddress_index ) = = 8 , " cryptonote::subaddress_index shall be 8 bytes length " ) ;
memmove ( this - > buffer_send + offset , & index , sizeof ( cryptonote : : subaddress_index ) ) ;
offset + = 8 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
2019-09-25 12:31:14 +00:00
offset = 0 ;
this - > receive_secret ( ( unsigned char * ) sub_sec . data , offset ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
crypto : : secret_key sub_sec_clear = hw : : ledger : : decrypt ( sub_sec ) ;
hw : : ledger : : check32 ( " get_subaddress_secret_key " , " sub_sec " , sub_sec_x . data , sub_sec_clear . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return sub_sec ;
2018-02-20 16:01:27 +00:00
}
/* ======================================================================= */
/* DERIVATION & KEY */
/* ======================================================================= */
bool device_ledger : : verify_keys ( const crypto : : secret_key & secret_key , const crypto : : public_key & public_key ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-12-07 15:46:52 +00:00
int offset ;
2018-03-26 10:38:38 +00:00
2018-06-20 09:40:09 +00:00
offset = set_command_header_noopt ( INS_VERIFY_KEY ) ;
2018-02-20 16:01:27 +00:00
//sec
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) secret_key . data , offset ) ;
2018-02-20 16:01:27 +00:00
//pub
memmove ( this - > buffer_send + offset , public_key . data , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
uint32_t verified =
this - > buffer_recv [ 0 ] < < 24 |
this - > buffer_recv [ 1 ] < < 16 |
this - > buffer_recv [ 2 ] < < 8 |
this - > buffer_recv [ 3 ] < < 0 ;
return verified = = 1 ;
}
bool device_ledger : : scalarmultKey ( rct : : key & aP , const rct : : key & P , const rct : : key & a ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
2018-03-05 13:46:15 +00:00
const rct : : key P_x = P ;
const rct : : key a_x = hw : : ledger : : decrypt ( a ) ;
rct : : key aP_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " scalarmultKey: [[IN]] P " , ( char * ) P_x . bytes , 32 ) ;
log_hexbuffer ( " scalarmultKey: [[IN]] a " , ( char * ) a_x . bytes , 32 ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > scalarmultKey ( aP_x , P_x , a_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " scalarmultKey: [[OUT]] aP " , ( char * ) aP_x . bytes , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_SECRET_SCAL_MUL_KEY ) ;
2018-02-20 16:01:27 +00:00
//pub
memmove ( this - > buffer_send + offset , P . bytes , 32 ) ;
offset + = 32 ;
//sec
2019-09-25 12:31:14 +00:00
this - > send_secret ( a . bytes , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
//pub key
memmove ( aP . bytes , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
2018-03-05 13:46:15 +00:00
hw : : ledger : : check32 ( " scalarmultKey " , " mulkey " , ( char * ) aP_x . bytes , ( char * ) aP . bytes ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : scalarmultBase ( rct : : key & aG , const rct : : key & a ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
2018-03-05 13:46:15 +00:00
const rct : : key a_x = hw : : ledger : : decrypt ( a ) ;
rct : : key aG_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " scalarmultKey: [[IN]] a " , ( char * ) a_x . bytes , 32 ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > scalarmultBase ( aG_x , a_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " scalarmultKey: [[OUT]] aG " , ( char * ) aG_x . bytes , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_SECRET_SCAL_MUL_BASE ) ;
2018-02-20 16:01:27 +00:00
//sec
2019-09-25 12:31:14 +00:00
this - > send_secret ( a . bytes , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
//pub key
memmove ( aG . bytes , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
2018-03-05 13:46:15 +00:00
hw : : ledger : : check32 ( " scalarmultBase " , " mulkey " , ( char * ) aG_x . bytes , ( char * ) aG . bytes ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : sc_secret_add ( crypto : : secret_key & r , const crypto : : secret_key & a , const crypto : : secret_key & b ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2019-09-25 12:31:14 +00:00
int offset ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : secret_key a_x = hw : : ledger : : decrypt ( a ) ;
const crypto : : secret_key b_x = hw : : ledger : : decrypt ( b ) ;
crypto : : secret_key r_x ;
2019-03-21 16:22:43 +00:00
rct : : key aG_x ;
log_hexbuffer ( " sc_secret_add: [[IN]] a " , ( char * ) a_x . data , 32 ) ;
log_hexbuffer ( " sc_secret_add: [[IN]] b " , ( char * ) b_x . data , 32 ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > sc_secret_add ( r_x , a_x , b_x ) ;
2019-03-21 16:22:43 +00:00
log_hexbuffer ( " sc_secret_add: [[OUT]] aG " , ( char * ) r_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2019-09-25 12:31:14 +00:00
offset = set_command_header_noopt ( INS_SECRET_KEY_ADD ) ;
2018-02-20 16:01:27 +00:00
//sec key
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) a . data , offset ) ;
2018-02-20 16:01:27 +00:00
//sec key
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) b . data , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
2019-09-25 12:31:14 +00:00
//sec key
offset = 0 ;
this - > receive_secret ( ( unsigned char * ) r . data , offset ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
crypto : : secret_key r_clear = hw : : ledger : : decrypt ( r ) ;
hw : : ledger : : check32 ( " sc_secret_add " , " r " , r_x . data , r_clear . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
2018-03-05 05:24:48 +00:00
crypto : : secret_key device_ledger : : generate_keys ( crypto : : public_key & pub , crypto : : secret_key & sec , const crypto : : secret_key & recovery_key , bool recover ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2019-09-25 12:31:14 +00:00
int offset ;
2018-03-26 10:38:38 +00:00
if ( recover ) {
throw std : : runtime_error ( " device generate key does not support recover " ) ;
}
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
crypto : : public_key pub_x ;
crypto : : secret_key sec_x ;
2019-03-21 16:22:43 +00:00
crypto : : secret_key recovery_key_x ;
if ( recover ) {
recovery_key_x = hw : : ledger : : decrypt ( recovery_key ) ;
log_hexbuffer ( " generate_keys: [[IN]] pub " , ( char * ) recovery_key_x . data , 32 ) ;
}
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
send_simple ( INS_GENERATE_KEYPAIR ) ;
2018-02-20 16:01:27 +00:00
2019-09-25 12:31:14 +00:00
offset = 0 ;
2018-02-20 16:01:27 +00:00
//pub key
memmove ( pub . data , & this - > buffer_recv [ 0 ] , 32 ) ;
2019-09-25 12:31:14 +00:00
offset + = 32 ;
this - > receive_secret ( ( unsigned char * ) sec . data , offset ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
crypto : : secret_key sec_clear = hw : : ledger : : decrypt ( sec ) ;
sec_x = sec_clear ;
2019-03-21 16:22:43 +00:00
log_hexbuffer ( " generate_keys: [[OUT]] pub " , ( char * ) pub . data , 32 ) ;
log_hexbuffer ( " generate_keys: [[OUT]] sec " , ( char * ) sec_clear . data , 32 ) ;
2018-02-20 16:01:27 +00:00
crypto : : secret_key_to_public_key ( sec_x , pub_x ) ;
hw : : ledger : : check32 ( " generate_keys " , " pub " , pub_x . data , pub . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return sec ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : generate_key_derivation ( const crypto : : public_key & pub , const crypto : : secret_key & sec , crypto : : key_derivation & derivation ) {
2018-03-26 10:55:48 +00:00
bool r = false ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : public_key pub_x = pub ;
2019-03-21 16:22:43 +00:00
const crypto : : secret_key sec_x = ( sec = = rct : : rct2sk ( rct : : I ) ) ? sec : hw : : ledger : : decrypt ( sec ) ;
2018-02-20 16:01:27 +00:00
crypto : : key_derivation derivation_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " generate_key_derivation: [[IN]] pub " , pub_x . data , 32 ) ;
log_hexbuffer ( " generate_key_derivation: [[IN]] sec " , sec_x . data , 32 ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > generate_key_derivation ( pub_x , sec_x , derivation_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " generate_key_derivation: [[OUT]] derivation " , derivation_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-03-26 10:55:48 +00:00
if ( ( this - > mode = = TRANSACTION_PARSE ) & & has_view_key ) {
//A derivation is resquested in PASRE mode and we have the view key,
//so do that wihtout the device and return the derivation unencrypted.
MDEBUG ( " generate_key_derivation : PARSE mode with known viewkey " ) ;
//Note derivation in PARSE mode can only happen with viewkey, so assert it!
assert ( is_fake_view_key ( sec ) ) ;
r = crypto : : generate_key_derivation ( pub , this - > viewkey , derivation ) ;
} else {
2021-06-04 15:41:42 +00:00
AUTO_LOCK_CMD ( ) ;
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_GEN_KEY_DERIVATION ) ;
2018-02-20 16:01:27 +00:00
//pub
memmove ( this - > buffer_send + offset , pub . data , 32 ) ;
offset + = 32 ;
//sec
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) sec . data , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
2019-09-25 12:31:14 +00:00
offset = 0 ;
2018-02-20 16:01:27 +00:00
//derivattion data
2019-09-25 12:31:14 +00:00
this - > receive_secret ( ( unsigned char * ) derivation . data , offset ) ;
2018-03-26 10:55:48 +00:00
r = true ;
}
# ifdef DEBUG_HWDEVICE
crypto : : key_derivation derivation_clear ;
2019-03-21 16:22:43 +00:00
if ( ( this - > mode = = TRANSACTION_PARSE ) & & has_view_key ) {
derivation_clear = derivation ;
} else {
derivation_clear = hw : : ledger : : decrypt ( derivation ) ;
}
2018-03-26 10:55:48 +00:00
hw : : ledger : : check32 ( " generate_key_derivation " , " derivation " , derivation_x . data , derivation_clear . data ) ;
# endif
2018-02-20 16:01:27 +00:00
2018-03-26 10:55:48 +00:00
return r ;
2018-02-20 16:01:27 +00:00
}
2018-04-09 14:07:11 +00:00
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 ) {
const crypto : : public_key * pkey = NULL ;
if ( derivation = = main_derivation ) {
pkey = & tx_pub_key ;
MDEBUG ( " conceal derivation with main tx pub key " ) ;
} else {
for ( size_t n = 0 ; n < additional_derivations . size ( ) ; + + n ) {
if ( derivation = = additional_derivations [ n ] ) {
pkey = & additional_tx_pub_keys [ n ] ;
2020-05-19 15:56:30 +00:00
MDEBUG ( " conceal derivation with additional tx pub key " ) ;
2018-04-09 14:07:11 +00:00
break ;
}
}
}
ASSERT_X ( pkey , " Mismatched derivation on scan info " ) ;
return this - > generate_key_derivation ( * pkey , crypto : : null_skey , derivation ) ;
}
2018-02-20 16:01:27 +00:00
bool device_ledger : : derivation_to_scalar ( const crypto : : key_derivation & derivation , const size_t output_index , crypto : : ec_scalar & res ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : key_derivation derivation_x = hw : : ledger : : decrypt ( derivation ) ;
const size_t output_index_x = output_index ;
crypto : : ec_scalar res_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " derivation_to_scalar: [[IN]] derivation " , derivation_x . data , 32 ) ;
log_message ( " derivation_to_scalar: [[IN]] output_index " , std : : to_string ( output_index_x ) ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > derivation_to_scalar ( derivation_x , output_index_x , res_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " derivation_to_scalar: [[OUT]] res " , res_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_DERIVATION_TO_SCALAR ) ;
2019-09-25 12:31:14 +00:00
//derivation
this - > send_secret ( ( unsigned char * ) derivation . data , offset ) ;
2018-02-20 16:01:27 +00:00
//index
this - > buffer_send [ offset + 0 ] = output_index > > 24 ;
this - > buffer_send [ offset + 1 ] = output_index > > 16 ;
this - > buffer_send [ offset + 2 ] = output_index > > 8 ;
this - > buffer_send [ offset + 3 ] = output_index > > 0 ;
offset + = 4 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
2019-09-25 12:31:14 +00:00
//derivation data
offset = 0 ;
this - > receive_secret ( ( unsigned char * ) res . data , offset ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
crypto : : ec_scalar res_clear = hw : : ledger : : decrypt ( res ) ;
hw : : ledger : : check32 ( " derivation_to_scalar " , " res " , res_x . data , res_clear . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
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 ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : key_derivation derivation_x = hw : : ledger : : decrypt ( derivation ) ;
const std : : size_t output_index_x = output_index ;
const crypto : : secret_key sec_x = hw : : ledger : : decrypt ( sec ) ;
crypto : : secret_key derived_sec_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " derive_secret_key: [[IN]] derivation " , derivation_x . data , 32 ) ;
log_message ( " derive_secret_key: [[IN]] index " , std : : to_string ( output_index_x ) ) ;
log_hexbuffer ( " derive_secret_key: [[IN]] sec " , sec_x . data , 32 ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > derive_secret_key ( derivation_x , output_index_x , sec_x , derived_sec_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " derive_secret_key: [[OUT]] derived_sec " , derived_sec_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_DERIVE_SECRET_KEY ) ;
2018-02-20 16:01:27 +00:00
//derivation
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) derivation . data , offset ) ;
2018-02-20 16:01:27 +00:00
//index
this - > buffer_send [ offset + 0 ] = output_index > > 24 ;
this - > buffer_send [ offset + 1 ] = output_index > > 16 ;
this - > buffer_send [ offset + 2 ] = output_index > > 8 ;
this - > buffer_send [ offset + 3 ] = output_index > > 0 ;
offset + = 4 ;
//sec
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) sec . data , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
2019-09-25 12:31:14 +00:00
offset = 0 ;
//sec key
this - > receive_secret ( ( unsigned char * ) derived_sec . data , offset ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
crypto : : secret_key derived_sec_clear = hw : : ledger : : decrypt ( derived_sec ) ;
hw : : ledger : : check32 ( " derive_secret_key " , " derived_sec " , derived_sec_x . data , derived_sec_clear . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
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 ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : key_derivation derivation_x = hw : : ledger : : decrypt ( derivation ) ;
const std : : size_t output_index_x = output_index ;
const crypto : : public_key pub_x = pub ;
crypto : : public_key derived_pub_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " derive_public_key: [[IN]] derivation " , derivation_x . data , 32 ) ;
log_message ( " derive_public_key: [[IN]] output_index " , std : : to_string ( output_index_x ) ) ;
log_hexbuffer ( " derive_public_key: [[IN]] pub " , pub_x . data , 32 ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > derive_public_key ( derivation_x , output_index_x , pub_x , derived_pub_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " derive_public_key: [[OUT]] derived_pub " , derived_pub_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_DERIVE_PUBLIC_KEY ) ;
2018-02-20 16:01:27 +00:00
//derivation
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) derivation . data , offset ) ;
2018-02-20 16:01:27 +00:00
//index
this - > buffer_send [ offset + 0 ] = output_index > > 24 ;
this - > buffer_send [ offset + 1 ] = output_index > > 16 ;
this - > buffer_send [ offset + 2 ] = output_index > > 8 ;
this - > buffer_send [ offset + 3 ] = output_index > > 0 ;
offset + = 4 ;
//pub
memmove ( this - > buffer_send + offset , pub . data , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
//pub key
memmove ( derived_pub . data , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " derive_public_key " , " derived_pub " , derived_pub_x . data , derived_pub . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : secret_key_to_public_key ( const crypto : : secret_key & sec , crypto : : public_key & pub ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : secret_key sec_x = hw : : ledger : : decrypt ( sec ) ;
crypto : : public_key pub_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " secret_key_to_public_key: [[IN]] sec " , sec_x . data , 32 ) ;
2018-03-05 13:46:15 +00:00
bool rc = this - > controle_device - > secret_key_to_public_key ( sec_x , pub_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " secret_key_to_public_key: [[OUT]] pub " , pub_x . data , 32 ) ;
2018-03-05 13:46:15 +00:00
if ( ! rc ) {
2019-03-21 16:22:43 +00:00
log_message ( " FAIL secret_key_to_public_key " , " secret_key rejected " ) ;
2018-03-05 13:46:15 +00:00
}
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_SECRET_KEY_TO_PUBLIC_KEY ) ;
2018-02-20 16:01:27 +00:00
//sec key
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) sec . data , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
//pub key
memmove ( pub . data , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " secret_key_to_public_key " , " pub " , pub_x . data , pub . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : generate_key_image ( const crypto : : public_key & pub , const crypto : : secret_key & sec , crypto : : key_image & image ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : public_key pub_x = pub ;
const crypto : : secret_key sec_x = hw : : ledger : : decrypt ( sec ) ;
crypto : : key_image image_x ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " generate_key_image: [[IN]] pub " , pub_x . data , 32 ) ;
log_hexbuffer ( " generate_key_image: [[IN]] sec " , sec_x . data , 32 ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > generate_key_image ( pub_x , sec_x , image_x ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " generate_key_image: [[OUT]] image " , image_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_GEN_KEY_IMAGE ) ;
2018-02-20 16:01:27 +00:00
//pub
memmove ( this - > buffer_send + offset , pub . data , 32 ) ;
offset + = 32 ;
//sec
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) sec . data , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
//pub key
memmove ( image . data , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " generate_key_image " , " image " , image_x . data , image . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
/* ======================================================================= */
/* TRANSACTION */
/* ======================================================================= */
2019-03-21 16:22:43 +00:00
void device_ledger : : generate_tx_proof ( const crypto : : hash & prefix_hash ,
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 ,
crypto : : signature & sig ) {
AUTO_LOCK_CMD ( ) ;
# ifdef DEBUG_HWDEVICE
const crypto : : hash prefix_hash_x = prefix_hash ;
const crypto : : public_key R_x = R ;
const crypto : : public_key A_x = A ;
const boost : : optional < crypto : : public_key > B_x = B ;
const crypto : : public_key D_x = D ;
const crypto : : secret_key r_x = hw : : ledger : : decrypt ( r ) ;
crypto : : signature sig_x ;
log_hexbuffer ( " generate_tx_proof: [[IN]] prefix_hash " , prefix_hash_x . data , 32 ) ;
log_hexbuffer ( " generate_tx_proof: [[IN]] R " , R_x . data , 32 ) ;
log_hexbuffer ( " generate_tx_proof: [[IN]] A " , A_x . data , 32 ) ;
if ( B_x ) {
log_hexbuffer ( " generate_tx_proof: [[IN]] B " , ( * B_x ) . data , 32 ) ;
}
log_hexbuffer ( " generate_tx_proof: [[IN]] D " , D_x . data , 32 ) ;
log_hexbuffer ( " generate_tx_proof: [[IN]] r " , r_x . data , 32 ) ;
# endif
int offset = set_command_header ( INS_GET_TX_PROOF ) ;
//options
this - > buffer_send [ offset ] = B ? 0x01 : 0x00 ;
offset + = 1 ;
//prefix_hash
memmove ( & this - > buffer_send [ offset ] , prefix_hash . data , 32 ) ;
offset + = 32 ;
// R
memmove ( & this - > buffer_send [ offset ] , R . data , 32 ) ;
offset + = 32 ;
// A
memmove ( & this - > buffer_send [ offset ] , A . data , 32 ) ;
offset + = 32 ;
// B
if ( B ) {
memmove ( & this - > buffer_send [ offset ] , ( * B ) . data , 32 ) ;
} else {
memset ( & this - > buffer_send [ offset ] , 0 , 32 ) ;
}
offset + = 32 ;
// D
memmove ( & this - > buffer_send [ offset ] , D . data , 32 ) ;
offset + = 32 ;
// r
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) r . data , offset ) ;
2019-03-21 16:22:43 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
memmove ( sig . c . data , & this - > buffer_recv [ 0 ] , 32 ) ;
memmove ( sig . r . data , & this - > buffer_recv [ 32 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
log_hexbuffer ( " GENERATE_TX_PROOF: **c** " , sig . c . data , sizeof ( sig . c . data ) ) ;
log_hexbuffer ( " GENERATE_TX_PROOF: **r** " , sig . r . data , sizeof ( sig . r . data ) ) ;
this - > controle_device - > generate_tx_proof ( prefix_hash_x , R_x , A_x , B_x , D_x , r_x , sig_x ) ;
2019-10-01 15:28:23 +00:00
MDEBUG ( " FAIL is normal if random is not fixed in proof " ) ;
2019-03-21 16:22:43 +00:00
hw : : ledger : : check32 ( " generate_tx_proof " , " c " , sig_x . c . data , sig . c . data ) ;
hw : : ledger : : check32 ( " generate_tx_proof " , " r " , sig_x . r . data , sig . r . data ) ;
# endif
}
2018-02-20 16:01:27 +00:00
bool device_ledger : : open_tx ( crypto : : secret_key & tx_key ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2019-09-25 12:31:14 +00:00
this - > lock ( ) ;
2018-02-20 16:01:27 +00:00
key_map . clear ( ) ;
2019-09-25 12:31:14 +00:00
hmac_map . clear ( ) ;
this - > tx_in_progress = true ;
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_OPEN_TX , 0x01 ) ;
2018-02-20 16:01:27 +00:00
//account
this - > buffer_send [ offset + 0 ] = 0x00 ;
this - > buffer_send [ offset + 1 ] = 0x00 ;
this - > buffer_send [ offset + 2 ] = 0x00 ;
this - > buffer_send [ offset + 3 ] = 0x00 ;
offset + = 4 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
2019-09-25 12:31:14 +00:00
//skip R, receive: r, r_hmac, fake_a, a_hmac, fake_b, hmac_b
unsigned char tmp [ 32 ] ;
offset = 32 ;
this - > receive_secret ( ( unsigned char * ) tx_key . data , offset ) ;
this - > receive_secret ( tmp , offset ) ;
this - > receive_secret ( tmp , offset ) ;
2019-03-21 16:22:43 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : secret_key r_x = hw : : ledger : : decrypt ( tx_key ) ;
log_hexbuffer ( " open_tx: [[OUT]] R " , ( char * ) & this - > buffer_recv [ 0 ] , 32 ) ;
log_hexbuffer ( " open_tx: [[OUT]] r " , r_x . data , 32 ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
2020-04-03 20:56:55 +00:00
void device_ledger : : get_transaction_prefix_hash ( const cryptonote : : transaction_prefix & tx , crypto : : hash & h ) {
AUTO_LOCK_CMD ( ) ;
int pref_length = 0 , pref_offset = 0 , offset = 0 ;
# ifdef DEBUG_HWDEVICE
crypto : : hash h_x ;
this - > controle_device - > get_transaction_prefix_hash ( tx , h_x ) ;
MDEBUG ( " get_transaction_prefix_hash [[IN]] h_x/1 " < < h_x ) ;
# endif
std : : ostringstream s_x ;
binary_archive < true > a_x ( s_x ) ;
CHECK_AND_ASSERT_THROW_MES ( : : serialization : : serialize ( a_x , const_cast < cryptonote : : transaction_prefix & > ( tx ) ) ,
" unable to serialize transaction prefix " ) ;
pref_length = s_x . str ( ) . size ( ) ;
//auto pref = std::make_unique<unsigned char[]>(pref_length);
auto uprt_pref = std : : unique_ptr < unsigned char [ ] > { new unsigned char [ pref_length ] } ;
unsigned char * pref = uprt_pref . get ( ) ;
memmove ( pref , s_x . str ( ) . data ( ) , pref_length ) ;
offset = set_command_header_noopt ( INS_PREFIX_HASH , 1 ) ;
pref_offset = 0 ;
unsigned char v ;
//version as varint
do {
v = pref [ pref_offset ] ;
this - > buffer_send [ offset ] = v ;
offset + = 1 ;
pref_offset + = 1 ;
} while ( v & 0x80 ) ;
//locktime as var int
do {
v = pref [ pref_offset ] ;
this - > buffer_send [ offset ] = v ;
offset + = 1 ;
pref_offset + = 1 ;
} while ( v & 0x80 ) ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange_wait_on_input ( ) ;
//hash remains
int cnt = 0 ;
while ( pref_offset < pref_length ) {
int len ;
cnt + + ;
offset = set_command_header ( INS_PREFIX_HASH , 2 , cnt ) ;
len = pref_length - pref_offset ;
//options
2020-05-27 12:57:05 +00:00
if ( len > ( BUFFER_SEND_SIZE - offset - 3 ) ) {
len = BUFFER_SEND_SIZE - offset - 3 ;
2020-04-03 20:56:55 +00:00
this - > buffer_send [ offset ] = 0x80 ;
} else {
this - > buffer_send [ offset ] = 0x00 ;
}
offset + = 1 ;
//send chunk
memmove ( & this - > buffer_send [ offset ] , pref + pref_offset , len ) ;
offset + = len ;
pref_offset + = len ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
}
memmove ( h . data , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check8 ( " prefix_hash " , " h " , h_x . data , h . data ) ;
# endif
}
2018-03-05 05:24:48 +00:00
bool device_ledger : : encrypt_payment_id ( crypto : : hash8 & payment_id , const crypto : : public_key & public_key , const crypto : : secret_key & secret_key ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const crypto : : public_key public_key_x = public_key ;
const crypto : : secret_key secret_key_x = hw : : ledger : : decrypt ( secret_key ) ;
crypto : : hash8 payment_id_x = payment_id ;
2019-03-21 16:22:43 +00:00
log_hexbuffer ( " encrypt_payment_id: [[IN]] payment_id " , payment_id_x . data , 32 ) ;
log_hexbuffer ( " encrypt_payment_id: [[IN]] public_key " , public_key_x . data , 32 ) ;
log_hexbuffer ( " encrypt_payment_id: [[IN]] secret_key " , secret_key_x . data , 32 ) ;
2018-03-26 10:38:38 +00:00
this - > controle_device - > encrypt_payment_id ( payment_id_x , public_key_x , secret_key_x ) ;
2019-03-21 16:22:43 +00:00
log_hexbuffer ( " encrypt_payment_id: [[OUT]] payment_id " , payment_id_x . data , 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_STEALTH ) ;
2018-02-20 16:01:27 +00:00
//pub
memmove ( & this - > buffer_send [ offset ] , public_key . data , 32 ) ;
offset + = 32 ;
//sec
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) secret_key . data , offset ) ;
2018-02-20 16:01:27 +00:00
//id
memmove ( & this - > buffer_send [ offset ] , payment_id . data , 8 ) ;
offset + = 8 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
memmove ( payment_id . data , & this - > buffer_recv [ 0 ] , 8 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check8 ( " stealth " , " payment_id " , payment_id_x . data , payment_id . data ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
2018-12-11 09:20:21 +00:00
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 ,
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 ) {
AUTO_LOCK_CMD ( ) ;
# ifdef DEBUG_HWDEVICE
const size_t & tx_version_x = tx_version ;
2019-03-21 16:22:43 +00:00
const cryptonote : : account_keys sender_account_keys_x = hw : : ledger : : decrypt ( sender_account_keys ) ;
2018-12-11 09:20:21 +00:00
memmove ( ( void * ) sender_account_keys_x . m_view_secret_key . data , dbg_viewkey . data , 32 ) ;
2018-12-11 09:20:21 +00:00
const crypto : : public_key txkey_pub_x = txkey_pub ;
const crypto : : secret_key tx_key_x = hw : : ledger : : decrypt ( tx_key ) ;
const cryptonote : : tx_destination_entry dst_entr_x = dst_entr ;
const boost : : optional < cryptonote : : account_public_address > change_addr_x = change_addr ;
const size_t output_index_x = output_index ;
const bool need_additional_txkeys_x = need_additional_txkeys ;
std : : vector < crypto : : secret_key > additional_tx_keys_x ;
2020-06-14 18:05:18 +00:00
for ( const auto & k : additional_tx_keys ) {
2018-12-11 09:20:21 +00:00
additional_tx_keys_x . push_back ( hw : : ledger : : decrypt ( k ) ) ;
}
2018-12-11 09:20:21 +00:00
std : : vector < crypto : : public_key > additional_tx_public_keys_x ;
std : : vector < rct : : key > amount_keys_x ;
crypto : : public_key out_eph_public_key_x ;
2019-03-21 16:22:43 +00:00
log_message ( " generate_output_ephemeral_keys: [[IN]] tx_version " , std : : to_string ( tx_version_x ) ) ;
//log_hexbuffer("generate_output_ephemeral_keys: [[IN]] sender_account_keys.view", sender_account_keys.m_sview_secret_key.data, 32);
//log_hexbuffer("generate_output_ephemeral_keys: [[IN]] sender_account_keys.spend", sender_account_keys.m_spend_secret_key.data, 32);
log_hexbuffer ( " generate_output_ephemeral_keys: [[IN]] txkey_pub " , txkey_pub_x . data , 32 ) ;
log_hexbuffer ( " generate_output_ephemeral_keys: [[IN]] tx_key " , tx_key_x . data , 32 ) ;
log_hexbuffer ( " generate_output_ephemeral_keys: [[IN]] dst_entr.view " , dst_entr_x . addr . m_view_public_key . data , 32 ) ;
log_hexbuffer ( " generate_output_ephemeral_keys: [[IN]] dst_entr.spend " , dst_entr_x . addr . m_spend_public_key . data , 32 ) ;
if ( change_addr ) {
log_hexbuffer ( " generate_output_ephemeral_keys: [[IN]] change_addr.view " , ( * change_addr_x ) . m_view_public_key . data , 32 ) ;
log_hexbuffer ( " generate_output_ephemeral_keys: [[IN]] change_addr.spend " , ( * change_addr_x ) . m_spend_public_key . data , 32 ) ;
}
log_message ( " generate_output_ephemeral_keys: [[IN]] output_index " , std : : to_string ( output_index_x ) ) ;
log_message ( " generate_output_ephemeral_keys: [[IN]] need_additional_txkeys " , std : : to_string ( need_additional_txkeys_x ) ) ;
if ( need_additional_txkeys_x ) {
log_hexbuffer ( " generate_output_ephemeral_keys: [[IN]] additional_tx_keys[oi] " , additional_tx_keys_x [ output_index ] . data , 32 ) ;
}
2018-12-11 09:20:21 +00:00
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 ,
additional_tx_public_keys_x , amount_keys_x , out_eph_public_key_x ) ;
2019-03-21 16:22:43 +00:00
if ( need_additional_txkeys_x ) {
log_hexbuffer ( " additional_tx_public_keys_x: [[OUT]] additional_tx_public_keys_x " , additional_tx_public_keys_x . back ( ) . data , 32 ) ;
}
log_hexbuffer ( " generate_output_ephemeral_keys: [[OUT]] amount_keys " , ( char * ) amount_keys_x . back ( ) . bytes , 32 ) ;
log_hexbuffer ( " generate_output_ephemeral_keys: [[OUT]] out_eph_public_key " , out_eph_public_key_x . data , 32 ) ;
2018-12-11 09:20:21 +00:00
# endif
2018-12-11 09:20:21 +00:00
ASSERT_X ( tx_version > 1 , " TX version not supported " < < tx_version ) ;
2018-12-11 09:20:21 +00:00
// make additional tx pubkey if necessary
cryptonote : : keypair additional_txkey ;
if ( need_additional_txkeys ) {
additional_txkey . sec = additional_tx_keys [ output_index ] ;
}
int offset = set_command_header_noopt ( INS_GEN_TXOUT_KEYS ) ;
//tx_version
this - > buffer_send [ offset + 0 ] = tx_version > > 24 ;
this - > buffer_send [ offset + 1 ] = tx_version > > 16 ;
this - > buffer_send [ offset + 2 ] = tx_version > > 8 ;
this - > buffer_send [ offset + 3 ] = tx_version > > 0 ;
offset + = 4 ;
2018-12-11 09:20:21 +00:00
//tx_key
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) tx_key . data , offset ) ;
2018-12-11 09:20:21 +00:00
//txkey_pub
memmove ( & this - > buffer_send [ offset ] , txkey_pub . data , 32 ) ;
2018-12-11 09:20:21 +00:00
offset + = 32 ;
//Aout
memmove ( & this - > buffer_send [ offset ] , dst_entr . addr . m_view_public_key . data , 32 ) ;
offset + = 32 ;
//Bout
memmove ( & this - > buffer_send [ offset ] , dst_entr . addr . m_spend_public_key . data , 32 ) ;
offset + = 32 ;
//output index
this - > buffer_send [ offset + 0 ] = output_index > > 24 ;
this - > buffer_send [ offset + 1 ] = output_index > > 16 ;
this - > buffer_send [ offset + 2 ] = output_index > > 8 ;
this - > buffer_send [ offset + 3 ] = output_index > > 0 ;
offset + = 4 ;
//is_change,
2019-03-21 16:22:43 +00:00
bool is_change = ( change_addr & & dst_entr . addr = = * change_addr ) ;
2018-12-11 09:20:21 +00:00
this - > buffer_send [ offset ] = is_change ;
offset + + ;
//is_subaddress
this - > buffer_send [ offset ] = dst_entr . is_subaddress ;
offset + + ;
//need_additional_key
this - > buffer_send [ offset ] = need_additional_txkeys ;
offset + + ;
2019-03-21 16:22:43 +00:00
//additional_tx_key
2018-12-11 09:20:21 +00:00
if ( need_additional_txkeys ) {
2019-09-25 12:31:14 +00:00
this - > send_secret ( ( unsigned char * ) additional_txkey . sec . data , offset ) ;
2018-12-11 09:20:21 +00:00
} else {
memset ( & this - > buffer_send [ offset ] , 0 , 32 ) ;
2019-09-25 12:31:14 +00:00
offset + = 32 ;
2018-12-11 09:20:21 +00:00
}
2019-03-21 16:22:43 +00:00
2018-12-11 09:20:21 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
offset = 0 ;
unsigned int recv_len = this - > length_recv ;
2018-12-11 09:20:21 +00:00
//if (tx_version > 1)
2019-03-21 16:22:43 +00:00
{
2020-05-19 15:56:30 +00:00
ASSERT_X ( recv_len > = 32 , " Not enough data from device " ) ;
2018-12-11 09:20:21 +00:00
crypto : : secret_key scalar1 ;
2019-09-25 12:31:14 +00:00
this - > receive_secret ( ( unsigned char * ) scalar1 . data , offset ) ;
2018-12-11 09:20:21 +00:00
amount_keys . push_back ( rct : : sk2rct ( scalar1 ) ) ;
recv_len - = 32 ;
}
2020-05-19 15:56:30 +00:00
ASSERT_X ( recv_len > = 32 , " Not enough data from device " ) ;
2018-12-11 09:20:21 +00:00
memmove ( out_eph_public_key . data , & this - > buffer_recv [ offset ] , 32 ) ;
recv_len - = 32 ;
2018-12-11 09:20:21 +00:00
offset + = 32 ;
if ( need_additional_txkeys )
{
2020-05-19 15:56:30 +00:00
ASSERT_X ( recv_len > = 32 , " Not enough data from device " ) ;
2018-12-11 09:20:21 +00:00
memmove ( additional_txkey . pub . data , & this - > buffer_recv [ offset ] , 32 ) ;
additional_tx_public_keys . push_back ( additional_txkey . pub ) ;
offset + = 32 ;
recv_len - = 32 ;
}
2018-12-11 09:20:21 +00:00
// add ABPkeys
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 ,
need_additional_txkeys , output_index ,
amount_keys . back ( ) , out_eph_public_key ) ;
# ifdef DEBUG_HWDEVICE
2018-12-11 09:20:21 +00:00
log_hexbuffer ( " generate_output_ephemeral_keys: clear amount_key " , ( const char * ) hw : : ledger : : decrypt ( amount_keys . back ( ) ) . bytes , 32 ) ;
2018-12-11 09:20:21 +00:00
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 ) ;
if ( need_additional_txkeys ) {
2018-12-11 09:20:21 +00:00
hw : : ledger : : check32 ( " generate_output_ephemeral_keys " , " additional_tx_key " , additional_tx_public_keys_x . back ( ) . data , additional_tx_public_keys . back ( ) . data ) ;
2019-03-21 16:22:43 +00:00
}
2018-12-11 09:20:21 +00:00
hw : : ledger : : check32 ( " generate_output_ephemeral_keys " , " out_eph_public_key " , out_eph_public_key_x . data , out_eph_public_key . data ) ;
# endif
return true ;
}
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 ,
const bool need_additional , const size_t real_output_index ,
const rct : : key & amount_key , const crypto : : public_key & out_eph_public_key ) {
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 ) ) ;
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
2018-12-11 09:20:21 +00:00
rct : : key device_ledger : : genCommitmentMask ( const rct : : key & AKout ) {
# ifdef DEBUG_HWDEVICE
const rct : : key AKout_x = hw : : ledger : : decrypt ( AKout ) ;
rct : : key mask_x ;
mask_x = this - > controle_device - > genCommitmentMask ( AKout_x ) ;
# endif
rct : : key mask ;
int offset = set_command_header_noopt ( INS_GEN_COMMITMENT_MASK ) ;
// AKout
2019-09-25 12:31:14 +00:00
this - > send_secret ( AKout . bytes , offset ) ;
2018-12-11 09:20:21 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
memmove ( mask . bytes , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " genCommitmentMask " , " mask " , ( const char * ) mask_x . bytes , ( const char * ) mask . bytes ) ;
# endif
return mask ;
}
2019-01-06 19:49:52 +00:00
bool device_ledger : : ecdhEncode ( rct : : ecdhTuple & unmasked , const rct : : key & AKout , bool short_amount ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const rct : : key AKout_x = hw : : ledger : : decrypt ( AKout ) ;
rct : : ecdhTuple unmasked_x = unmasked ;
2019-01-06 19:49:52 +00:00
this - > controle_device - > ecdhEncode ( unmasked_x , AKout_x , short_amount ) ;
2018-02-20 16:01:27 +00:00
# endif
2019-02-08 15:11:51 +00:00
int offset = set_command_header ( INS_BLIND ) ;
//options
this - > buffer_send [ offset ] = short_amount ? 0x02 : 0x00 ;
offset + = 1 ;
2018-02-20 16:01:27 +00:00
// AKout
2019-09-25 12:31:14 +00:00
this - > send_secret ( AKout . bytes , offset ) ;
2018-02-20 16:01:27 +00:00
//mask k
memmove ( this - > buffer_send + offset , unmasked . mask . bytes , 32 ) ;
offset + = 32 ;
//value v
memmove ( this - > buffer_send + offset , unmasked . amount . bytes , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
memmove ( unmasked . amount . bytes , & this - > buffer_recv [ 0 ] , 32 ) ;
memmove ( unmasked . mask . bytes , & this - > buffer_recv [ 32 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
2018-12-11 09:20:21 +00:00
MDEBUG ( " ecdhEncode: Akout: " < < AKout_x ) ;
2018-02-20 16:01:27 +00:00
hw : : ledger : : check32 ( " ecdhEncode " , " amount " , ( char * ) unmasked_x . amount . bytes , ( char * ) unmasked . amount . bytes ) ;
hw : : ledger : : check32 ( " ecdhEncode " , " mask " , ( char * ) unmasked_x . mask . bytes , ( char * ) unmasked . mask . bytes ) ;
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " Blind AKV input " , ( char * ) & this - > buffer_recv [ 64 ] , 3 * 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
2019-01-06 19:49:52 +00:00
bool device_ledger : : ecdhDecode ( rct : : ecdhTuple & masked , const rct : : key & AKout , bool short_amount ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const rct : : key AKout_x = hw : : ledger : : decrypt ( AKout ) ;
rct : : ecdhTuple masked_x = masked ;
2019-01-06 19:49:52 +00:00
this - > controle_device - > ecdhDecode ( masked_x , AKout_x , short_amount ) ;
2018-02-20 16:01:27 +00:00
# endif
2019-02-08 15:11:51 +00:00
int offset = set_command_header ( INS_UNBLIND ) ;
//options
this - > buffer_send [ offset ] = short_amount ? 0x02 : 0x00 ;
offset + = 1 ;
2018-02-20 16:01:27 +00:00
// AKout
2019-09-25 12:31:14 +00:00
this - > send_secret ( AKout . bytes , offset ) ;
2018-02-20 16:01:27 +00:00
//mask k
memmove ( this - > buffer_send + offset , masked . mask . bytes , 32 ) ;
offset + = 32 ;
//value v
memmove ( this - > buffer_send + offset , masked . amount . bytes , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
memmove ( masked . amount . bytes , & this - > buffer_recv [ 0 ] , 32 ) ;
memmove ( masked . mask . bytes , & this - > buffer_recv [ 32 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
2018-12-11 09:20:21 +00:00
MDEBUG ( " ecdhEncode: Akout: " < < AKout_x ) ;
2018-02-20 16:01:27 +00:00
hw : : ledger : : check32 ( " ecdhDecode " , " amount " , ( char * ) masked_x . amount . bytes , ( char * ) masked . amount . bytes ) ;
hw : : ledger : : check32 ( " ecdhDecode " , " mask " , ( char * ) masked_x . mask . bytes , ( char * ) masked . mask . bytes ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : mlsag_prehash ( const std : : string & blob , size_t inputs_size , size_t outputs_size ,
const rct : : keyV & hashes , const rct : : ctkeyV & outPk ,
rct : : key & prehash ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
unsigned int data_offset , C_offset , kv_offset , i ;
const char * data ;
# ifdef DEBUG_HWDEVICE
const std : : string blob_x = blob ;
size_t inputs_size_x = inputs_size ;
size_t outputs_size_x = outputs_size ;
const rct : : keyV hashes_x = hashes ;
const rct : : ctkeyV outPk_x = outPk ;
rct : : key prehash_x ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > mlsag_prehash ( blob_x , inputs_size_x , outputs_size_x , hashes_x , outPk_x , prehash_x ) ;
2018-02-20 16:01:27 +00:00
if ( inputs_size ) {
log_message ( " mlsag_prehash " , ( std : : string ( " inputs_size not null: " ) + std : : to_string ( inputs_size ) ) . c_str ( ) ) ;
}
this - > key_map . log ( ) ;
# endif
data = blob . data ( ) ;
// ====== u8 type, varint txnfee ======
2018-06-20 09:40:09 +00:00
int offset = set_command_header ( INS_VALIDATE , 0x01 , 0x01 ) ;
2018-02-20 16:01:27 +00:00
//options
this - > buffer_send [ offset ] = ( inputs_size = = 0 ) ? 0x00 : 0x80 ;
offset + = 1 ;
//type
2018-03-05 13:46:15 +00:00
uint8_t type = data [ 0 ] ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ offset ] = data [ 0 ] ;
offset + = 1 ;
//txnfee
data_offset = 1 ;
while ( data [ data_offset ] & 0x80 ) {
this - > buffer_send [ offset ] = data [ data_offset ] ;
offset + = 1 ;
data_offset + = 1 ;
}
this - > buffer_send [ offset ] = data [ data_offset ] ;
offset + = 1 ;
data_offset + = 1 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
2019-01-09 08:20:53 +00:00
// check fee user input
CHECK_AND_ASSERT_THROW_MES ( this - > exchange_wait_on_input ( ) = = 0 , " Fee denied on device. " ) ;
2018-02-20 16:01:27 +00:00
//pseudoOuts
2018-07-30 08:16:13 +00:00
if ( type = = rct : : RCTTypeSimple ) {
2018-03-05 13:46:15 +00:00
for ( i = 0 ; i < inputs_size ; i + + ) {
2018-06-20 09:40:09 +00:00
offset = set_command_header ( INS_VALIDATE , 0x01 , i + 2 ) ;
2018-03-05 13:46:15 +00:00
//options
this - > buffer_send [ offset ] = ( i = = inputs_size - 1 ) ? 0x00 : 0x80 ;
offset + = 1 ;
//pseudoOut
memmove ( this - > buffer_send + offset , data + data_offset , 32 ) ;
offset + = 32 ;
data_offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
}
2018-02-20 16:01:27 +00:00
}
// ====== Aout, Bout, AKout, C, v, k ======
kv_offset = data_offset ;
2019-06-09 13:02:16 +00:00
if ( type = = rct : : RCTTypeBulletproof2 | | type = = rct : : RCTTypeCLSAG ) {
2019-02-08 15:11:51 +00:00
C_offset = kv_offset + ( 8 ) * outputs_size ;
} else {
C_offset = kv_offset + ( 32 + 32 ) * outputs_size ;
}
2018-02-20 16:01:27 +00:00
for ( i = 0 ; i < outputs_size ; i + + ) {
ABPkeys outKeys ;
bool found ;
found = this - > key_map . find ( outPk [ i ] . dest , outKeys ) ;
if ( ! found ) {
log_hexbuffer ( " Pout not found " , ( char * ) outPk [ i ] . dest . bytes , 32 ) ;
CHECK_AND_ASSERT_THROW_MES ( found , " Pout not found " ) ;
}
2018-06-20 09:40:09 +00:00
offset = set_command_header ( INS_VALIDATE , 0x02 , i + 1 ) ;
2018-02-20 16:01:27 +00:00
//options
this - > buffer_send [ offset ] = ( i = = outputs_size - 1 ) ? 0x00 : 0x80 ;
2019-06-09 13:02:16 +00:00
this - > buffer_send [ offset ] | = ( type = = rct : : RCTTypeBulletproof2 | | type = = rct : : RCTTypeCLSAG ) ? 0x02 : 0x00 ;
2018-02-20 16:01:27 +00:00
offset + = 1 ;
2019-09-25 12:31:14 +00:00
//is_subaddress
this - > buffer_send [ offset ] = outKeys . is_subaddress ;
offset + + ;
//is_change_address
this - > buffer_send [ offset ] = outKeys . is_change_address ;
offset + + ;
//Aout
memmove ( this - > buffer_send + offset , outKeys . Aout . bytes , 32 ) ;
offset + = 32 ;
//Bout
memmove ( this - > buffer_send + offset , outKeys . Bout . bytes , 32 ) ;
offset + = 32 ;
//AKout
this - > send_secret ( outKeys . AKout . bytes , offset ) ;
2018-02-20 16:01:27 +00:00
//C
memmove ( this - > buffer_send + offset , data + C_offset , 32 ) ;
offset + = 32 ;
C_offset + = 32 ;
2019-06-09 13:02:16 +00:00
if ( type = = rct : : RCTTypeBulletproof2 | | type = = rct : : RCTTypeCLSAG ) {
2019-02-08 15:11:51 +00:00
//k
memset ( this - > buffer_send + offset , 0 , 32 ) ;
offset + = 32 ;
//v
memset ( this - > buffer_send + offset , 0 , 32 ) ;
memmove ( this - > buffer_send + offset , data + kv_offset , 8 ) ;
offset + = 32 ;
kv_offset + = 8 ;
} else {
//k
memmove ( this - > buffer_send + offset , data + kv_offset , 32 ) ;
offset + = 32 ;
kv_offset + = 32 ;
//v
memmove ( this - > buffer_send + offset , data + kv_offset , 32 ) ;
offset + = 32 ;
kv_offset + = 32 ;
}
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
2019-01-09 08:20:53 +00:00
// check transaction user input
CHECK_AND_ASSERT_THROW_MES ( this - > exchange_wait_on_input ( ) = = 0 , " Transaction denied on device. " ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
2019-02-06 14:05:06 +00:00
log_hexbuffer ( " Prehash AKV input " , ( char * ) & this - > buffer_recv [ 64 ] , 3 * 32 ) ;
2018-02-20 16:01:27 +00:00
# endif
}
// ====== C[], message, proof======
C_offset = kv_offset ;
for ( i = 0 ; i < outputs_size ; i + + ) {
2018-06-20 09:40:09 +00:00
offset = set_command_header ( INS_VALIDATE , 0x03 , i + 1 ) ;
2018-02-20 16:01:27 +00:00
//options
this - > buffer_send [ offset ] = 0x80 ;
offset + = 1 ;
//C
memmove ( this - > buffer_send + offset , data + C_offset , 32 ) ;
offset + = 32 ;
C_offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
}
2018-06-20 09:40:09 +00:00
offset = set_command_header_noopt ( INS_VALIDATE , 0x03 , i + 1 ) ;
2018-02-20 16:01:27 +00:00
//message
memmove ( this - > buffer_send + offset , hashes [ 0 ] . bytes , 32 ) ;
offset + = 32 ;
//proof
memmove ( this - > buffer_send + offset , hashes [ 2 ] . bytes , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
memmove ( prehash . bytes , this - > buffer_recv , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " mlsag_prehash " , " prehash " , ( char * ) prehash_x . bytes , ( char * ) prehash . bytes ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : mlsag_prepare ( const rct : : key & H , const rct : : key & xx ,
rct : : key & a , rct : : key & aG , rct : : key & aHP , rct : : key & II ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
const rct : : key H_x = H ;
const rct : : key xx_x = hw : : ledger : : decrypt ( xx ) ;
rct : : key a_x ;
rct : : key aG_x ;
rct : : key aHP_x ;
rct : : key II_x ;
# endif
2018-06-20 09:40:09 +00:00
int offset = set_command_header_noopt ( INS_MLSAG , 0x01 ) ;
2018-02-20 16:01:27 +00:00
//value H
memmove ( this - > buffer_send + offset , H . bytes , 32 ) ;
offset + = 32 ;
//mask xin
2019-09-25 12:31:14 +00:00
this - > send_secret ( xx . bytes , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
2019-09-25 12:31:14 +00:00
offset = 0 ;
this - > receive_secret ( a . bytes , offset ) ;
memmove ( aG . bytes , & this - > buffer_recv [ offset ] , 32 ) ;
offset + = 32 ;
memmove ( aHP . bytes , & this - > buffer_recv [ offset ] , 32 ) ;
offset + = 32 ;
memmove ( II . bytes , & this - > buffer_recv [ offset ] , 32 ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
a_x = hw : : ledger : : decrypt ( a ) ;
rct : : scalarmultBase ( aG_x , a_x ) ;
rct : : scalarmultKey ( aHP_x , H_x , a_x ) ;
rct : : scalarmultKey ( II_x , H_x , xx_x ) ;
hw : : ledger : : check32 ( " mlsag_prepare " , " AG " , ( char * ) aG_x . bytes , ( char * ) aG . bytes ) ;
hw : : ledger : : check32 ( " mlsag_prepare " , " aHP " , ( char * ) aHP_x . bytes , ( char * ) aHP . bytes ) ;
hw : : ledger : : check32 ( " mlsag_prepare " , " II " , ( char * ) II_x . bytes , ( char * ) II . bytes ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : mlsag_prepare ( rct : : key & a , rct : : key & aG ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2019-09-25 12:31:14 +00:00
int offset ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
rct : : key a_x ;
rct : : key aG_x ;
# endif
2018-06-20 09:40:09 +00:00
send_simple ( INS_MLSAG , 0x01 ) ;
2018-02-20 16:01:27 +00:00
2019-09-25 12:31:14 +00:00
offset = 0 ;
this - > receive_secret ( a . bytes , offset ) ;
memmove ( aG . bytes , & this - > buffer_recv [ offset ] , 32 ) ;
2018-02-20 16:01:27 +00:00
# ifdef DEBUG_HWDEVICE
a_x = hw : : ledger : : decrypt ( a ) ;
rct : : scalarmultBase ( aG_x , a_x ) ;
hw : : ledger : : check32 ( " mlsag_prepare " , " AG " , ( char * ) aG_x . bytes , ( char * ) aG . bytes ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
bool device_ledger : : mlsag_hash ( const rct : : keyV & long_message , rct : : key & c ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
size_t cnt ;
# ifdef DEBUG_HWDEVICE
const rct : : keyV long_message_x = long_message ;
rct : : key c_x ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > mlsag_hash ( long_message_x , c_x ) ;
2018-02-20 16:01:27 +00:00
# endif
cnt = long_message . size ( ) ;
for ( size_t i = 0 ; i < cnt ; i + + ) {
2018-06-20 09:40:09 +00:00
int offset = set_command_header ( INS_MLSAG , 0x02 , i + 1 ) ;
2018-02-20 16:01:27 +00:00
//options
this - > buffer_send [ offset ] =
( i = = ( cnt - 1 ) ) ? 0x00 : 0x80 ; //last
offset + = 1 ;
//msg part
memmove ( this - > buffer_send + offset , long_message [ i ] . bytes , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
}
memmove ( c . bytes , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " mlsag_hash " , " c " , ( char * ) c_x . bytes , ( char * ) c . bytes ) ;
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
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 ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-02-20 16:01:27 +00:00
CHECK_AND_ASSERT_THROW_MES ( dsRows < = rows , " dsRows greater than rows " ) ;
CHECK_AND_ASSERT_THROW_MES ( xx . size ( ) = = rows , " xx size does not match rows " ) ;
CHECK_AND_ASSERT_THROW_MES ( alpha . size ( ) = = rows , " alpha size does not match rows " ) ;
CHECK_AND_ASSERT_THROW_MES ( ss . size ( ) = = rows , " ss size does not match rows " ) ;
# ifdef DEBUG_HWDEVICE
const rct : : key c_x = c ;
const rct : : keyV xx_x = hw : : ledger : : decrypt ( xx ) ;
const rct : : keyV alpha_x = hw : : ledger : : decrypt ( alpha ) ;
const int rows_x = rows ;
const int dsRows_x = dsRows ;
rct : : keyV ss_x ( ss . size ( ) ) ;
2018-03-05 13:46:15 +00:00
this - > controle_device - > mlsag_sign ( c_x , xx_x , alpha_x , rows_x , dsRows_x , ss_x ) ;
2018-02-20 16:01:27 +00:00
# endif
for ( size_t j = 0 ; j < dsRows ; j + + ) {
2018-06-20 09:40:09 +00:00
int offset = set_command_header ( INS_MLSAG , 0x03 , j + 1 ) ;
2018-02-20 16:01:27 +00:00
//options
this - > buffer_send [ offset ] = 0x00 ;
if ( j = = ( dsRows - 1 ) ) {
this - > buffer_send [ offset ] | = 0x80 ; //last
}
offset + = 1 ;
//xx
2019-09-25 12:31:14 +00:00
this - > send_secret ( xx [ j ] . bytes , offset ) ;
2018-02-20 16:01:27 +00:00
//alpa
2019-09-25 12:31:14 +00:00
this - > send_secret ( alpha [ j ] . bytes , offset ) ;
2018-02-20 16:01:27 +00:00
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
//ss
memmove ( ss [ j ] . bytes , & this - > buffer_recv [ 0 ] , 32 ) ;
}
for ( size_t j = dsRows ; j < rows ; j + + ) {
sc_mulsub ( ss [ j ] . bytes , c . bytes , xx [ j ] . bytes , alpha [ j ] . bytes ) ;
}
# ifdef DEBUG_HWDEVICE
for ( size_t j = 0 ; j < rows ; j + + ) {
hw : : ledger : : check32 ( " mlsag_sign " , " ss[ " + std : : to_string ( j ) + " ] " , ( char * ) ss_x [ j ] . bytes , ( char * ) ss [ j ] . bytes ) ;
}
# endif
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
2020-03-31 15:11:51 +00:00
bool device_ledger : : clsag_prepare ( const rct : : key & p , const rct : : key & z , rct : : key & I , rct : : key & D , const rct : : key & H , rct : : key & a , rct : : key & aG , rct : : key & aH ) {
AUTO_LOCK_CMD ( ) ;
# ifdef DEBUG_HWDEVICE
const rct : : key p_x = hw : : ledger : : decrypt ( p ) ;
2020-08-28 10:01:57 +00:00
const rct : : key z_x = z ;
2020-03-31 15:11:51 +00:00
rct : : key I_x ;
rct : : key D_x ;
const rct : : key H_x = H ;
rct : : key a_x ;
rct : : key aG_x ;
rct : : key aH_x ;
this - > controle_device - > clsag_prepare ( p_x , z_x , I_x , D_x , H_x , a_x , aG_x , aH_x ) ;
# endif
/*
rct : : skpkGen ( a , aG ) ; // aG = a*G
rct : : scalarmultKey ( aH , H , a ) ; // aH = a*H
rct : : scalarmultKey ( I , H , p ) ; // I = p*H
rct : : scalarmultKey ( D , H , z ) ; // D = z*H
*/
int offset = set_command_header_noopt ( INS_CLSAG , 0x01 ) ;
//p
this - > send_secret ( p . bytes , offset ) ;
//z
2020-08-28 10:01:57 +00:00
memmove ( this - > buffer_send + offset , z . bytes , 32 ) ;
offset + = 32 ;
2020-03-31 15:11:51 +00:00
//H
memmove ( this - > buffer_send + offset , H . bytes , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
offset = 0 ;
//a
this - > receive_secret ( a . bytes , offset ) ;
//aG
memmove ( aG . bytes , this - > buffer_recv + offset , 32 ) ;
offset + = 32 ;
//aH
memmove ( aH . bytes , this - > buffer_recv + offset , 32 ) ;
offset + = 32 ;
//I = pH
memmove ( I . bytes , this - > buffer_recv + offset , 32 ) ;
offset + = 32 ;
//D = zH
memmove ( D . bytes , this - > buffer_recv + offset , 32 ) ;
offset + = 32 ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " clsag_prepare " , " I " , ( char * ) I_x . bytes , ( char * ) I . bytes ) ;
hw : : ledger : : check32 ( " clsag_prepare " , " D " , ( char * ) D_x . bytes , ( char * ) D . bytes ) ;
hw : : ledger : : check32 ( " clsag_prepare " , " a " , ( char * ) a_x . bytes , ( char * ) a . bytes ) ;
hw : : ledger : : check32 ( " clsag_prepare " , " aG " , ( char * ) aG_x . bytes , ( char * ) aG . bytes ) ;
hw : : ledger : : check32 ( " clsag_prepare " , " aH " , ( char * ) aH_x . bytes , ( char * ) aH . bytes ) ;
# endif
return true ;
}
bool device_ledger : : clsag_hash ( const rct : : keyV & data , rct : : key & hash ) {
AUTO_LOCK_CMD ( ) ;
# ifdef DEBUG_HWDEVICE
const rct : : keyV data_x = data ;
rct : : key hash_x ;
this - > controle_device - > mlsag_hash ( data_x , hash_x ) ;
# endif
size_t cnt ;
int offset ;
cnt = data . size ( ) ;
for ( size_t i = 0 ; i < cnt ; i + + ) {
offset = set_command_header ( INS_CLSAG , 0x02 , i + 1 ) ;
//options
this - > buffer_send [ offset ] = ( i = = ( cnt - 1 ) ) ? 0x00 : 0x80 ; //last
offset + = 1 ;
//msg part
memmove ( this - > buffer_send + offset , data [ i ] . bytes , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
}
//c/hash
memmove ( hash . bytes , & this - > buffer_recv [ 0 ] , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " mlsag_hash " , " hash " , ( char * ) hash_x . bytes , ( char * ) hash . bytes ) ;
# endif
return true ;
}
bool device_ledger : : clsag_sign ( const rct : : key & c , const rct : : key & a , const rct : : key & p , const rct : : key & z , const rct : : key & mu_P , const rct : : key & mu_C , rct : : key & s ) {
AUTO_LOCK_CMD ( ) ;
# ifdef DEBUG_HWDEVICE
const rct : : key c_x = c ;
const rct : : key a_x = hw : : ledger : : decrypt ( a ) ;
const rct : : key p_x = hw : : ledger : : decrypt ( p ) ;
2020-08-28 10:01:57 +00:00
const rct : : key z_x = z ;
2020-03-31 15:11:51 +00:00
const rct : : key mu_P_x = mu_P ;
const rct : : key mu_C_x = mu_C ;
rct : : key s_x ;
this - > controle_device - > clsag_sign ( c_x , a_x , p_x , z_x , mu_P_x , mu_C_x , s_x ) ;
# endif
/*
rct : : key s0_p_mu_P ;
sc_mul ( s0_p_mu_P . bytes , mu_P . bytes , p . bytes ) ;
rct : : key s0_add_z_mu_C ;
sc_muladd ( s0_add_z_mu_C . bytes , mu_C . bytes , z . bytes , s0_p_mu_P . bytes ) ;
sc_mulsub ( s . bytes , c . bytes , s0_add_z_mu_C . bytes , a . bytes ) ;
*/
int offset = set_command_header_noopt ( INS_CLSAG , 0x03 ) ;
//c
//discard, unse internal one
//a
this - > send_secret ( a . bytes , offset ) ;
//p
this - > send_secret ( p . bytes , offset ) ;
//z
2020-08-28 10:01:57 +00:00
memmove ( this - > buffer_send + offset , z . bytes , 32 ) ;
offset + = 32 ;
2020-03-31 15:11:51 +00:00
//mu_P
memmove ( this - > buffer_send + offset , mu_P . bytes , 32 ) ;
offset + = 32 ;
//mu_C
memmove ( this - > buffer_send + offset , mu_C . bytes , 32 ) ;
offset + = 32 ;
this - > buffer_send [ 4 ] = offset - 5 ;
this - > length_send = offset ;
this - > exchange ( ) ;
offset = 0 ;
//s
memmove ( s . bytes , this - > buffer_recv + offset , 32 ) ;
# ifdef DEBUG_HWDEVICE
hw : : ledger : : check32 ( " clsag_sign " , " s " , ( char * ) s_x . bytes , ( char * ) s . bytes ) ;
# endif
return true ;
}
2018-02-20 16:01:27 +00:00
bool device_ledger : : close_tx ( ) {
2018-03-26 10:38:38 +00:00
AUTO_LOCK_CMD ( ) ;
2018-06-20 09:40:09 +00:00
send_simple ( INS_CLOSE_TX ) ;
2019-09-25 12:31:14 +00:00
key_map . clear ( ) ;
hmac_map . clear ( ) ;
this - > tx_in_progress = false ;
this - > unlock ( ) ;
2018-03-26 10:38:38 +00:00
return true ;
2018-02-20 16:01:27 +00:00
}
/* ---------------------------------------------------------- */
static device_ledger * legder_device = NULL ;
void register_all ( std : : map < std : : string , std : : unique_ptr < device > > & registry ) {
if ( ! legder_device ) {
legder_device = new device_ledger ( ) ;
legder_device - > set_name ( " Ledger " ) ;
}
2018-03-04 18:56:48 +00:00
registry . insert ( std : : make_pair ( " Ledger " , std : : unique_ptr < device > ( legder_device ) ) ) ;
2018-02-20 16:01:27 +00:00
}
# else //WITH_DEVICE_LEDGER
void register_all ( std : : map < std : : string , std : : unique_ptr < device > > & registry ) {
}
# endif //WITH_DEVICE_LEDGER
}
}