Skip to content

Commit

Permalink
Merge pull request #3303
Browse files Browse the repository at this point in the history
e745c1e Code modifications to integrate Ledger HW device into monero-wallet-cli. (cslashm)
  • Loading branch information
fluffypony committed Mar 4, 2018
2 parents 421ab31 + e745c1e commit c7ace5f
Show file tree
Hide file tree
Showing 53 changed files with 4,130 additions and 223 deletions.
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,8 @@ if(STATIC AND NOT IOS)
endif()
endif()

find_package(PCSC)

add_definition_if_library_exists(c memset_s "string.h" HAVE_MEMSET_S)
add_definition_if_library_exists(c explicit_bzero "strings.h" HAVE_EXPLICIT_BZERO)
add_definition_if_function_found(strptime HAVE_STRPTIME)
Expand Down Expand Up @@ -456,6 +458,13 @@ endif()
include_directories(${LIBUNWIND_INCLUDE})
link_directories(${LIBUNWIND_LIBRARY_DIRS})

# Final setup for libpcsc
if (PCSC_FOUND)
add_definitions(-DHAVE_PCSC)
include_directories(${PCSC_INCLUDE_DIR})
link_directories(${LIBPCSC_LIBRARY_DIRS})
endif()

if(MSVC)
add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__")
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Dinline=__inline")
Expand Down
44 changes: 44 additions & 0 deletions cmake/FindPCSC.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# - Find PCSC
# Find the native PCSC includes and library
#
# PCSC_INCLUDE_DIR - where to find winscard.h, wintypes.h, etc.
# PCSC_LIBRARIES - List of libraries when using PCSC.
# PCSC_FOUND - True if PCSC found.


IF (PCSC_INCLUDE_DIR AND PCSC_LIBRARIES)
# Already in cache, be silent
SET(PCSC_FIND_QUIETLY TRUE)
ENDIF (PCSC_INCLUDE_DIR AND PCSC_LIBRARIES)

IF (NOT WIN32)
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(PC_PCSC libpcsclite)
ENDIF (NOT WIN32)

FIND_PATH(PCSC_INCLUDE_DIR winscard.h
HINTS
/usr/include/PCSC
${PC_PCSC_INCLUDEDIR}
${PC_PCSC_INCLUDE_DIRS}
PATH_SUFFIXES PCSC
)

FIND_LIBRARY(PCSC_LIBRARY NAMES pcsclite libpcsclite WinSCard PCSC
HINTS
${PC_PCSC_LIBDIR}
${PC_PCSC_LIBRARY_DIRS}
)

# handle the QUIETLY and REQUIRED arguments and set PCSC_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCSC DEFAULT_MSG PCSC_LIBRARY PCSC_INCLUDE_DIR)

IF(PCSC_FOUND)
SET( PCSC_LIBRARIES ${PCSC_LIBRARY} )
ELSE(PCSC_FOUND)
SET( PCSC_LIBRARIES )
ENDIF(PCSC_FOUND)

MARK_AS_ADVANCED( PCSC_LIBRARY PCSC_INCLUDE_DIR )
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,5 @@ endif()
if(PER_BLOCK_CHECKPOINT)
add_subdirectory(blocks)
endif()

add_subdirectory(device)
2 changes: 2 additions & 0 deletions src/crypto/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ set(crypto_sources
crypto-ops-data.c
crypto-ops.c
crypto.cpp
crypto_device.cpp
groestl.c
hash-extra-blake.c
hash-extra-groestl.c
Expand Down Expand Up @@ -77,6 +78,7 @@ monero_add_library(cncrypto
target_link_libraries(cncrypto
PUBLIC
epee
device
${Boost_SYSTEM_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES})
Expand Down
4 changes: 2 additions & 2 deletions src/crypto/chacha.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ namespace crypto {
chacha20(data, length, key.data(), reinterpret_cast<const uint8_t*>(&iv), cipher);
}

inline void generate_chacha_key(const void *data, size_t size, chacha_key& key) {
inline void generate_chacha_key(const void *data, size_t size, chacha_key& key, bool prehashed=false) {
static_assert(sizeof(chacha_key) <= sizeof(hash), "Size of hash must be at least that of chacha_key");
tools::scrubbed_arr<char, HASH_SIZE> pwd_hash;
crypto::cn_slow_hash(data, size, pwd_hash.data());
crypto::cn_slow_hash_pre(data, size, pwd_hash.data(), prehashed);
memcpy(&key, pwd_hash.data(), sizeof(key));
}

Expand Down
2 changes: 1 addition & 1 deletion src/crypto/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ namespace crypto {
return sc_isnonzero(&c2) == 0;
}

static void hash_to_ec(const public_key &key, ge_p3 &res) {
void crypto_ops::hash_to_ec(const public_key &key, ge_p3 &res) {
hash h;
ge_p2 point;
ge_p1p1 point2;
Expand Down
21 changes: 21 additions & 0 deletions src/crypto/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@
#include "hex.h"
#include "span.h"
#include "hash.h"
#include "device/device_declare.hpp"
extern "C" {
#include "crypto-ops.h"
}

namespace crypto {

Expand Down Expand Up @@ -113,6 +117,9 @@ namespace crypto {
void operator=(const crypto_ops &);
~crypto_ops();

static void hash_to_ec(const public_key &key, ge_p3 &res) ;
friend void hash_to_ec(const public_key &key, ge_p3 &res) ;

static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
static bool check_key(const public_key &);
Expand Down Expand Up @@ -149,6 +156,17 @@ namespace crypto {
const public_key *const *, std::size_t, const signature *);
};

secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover, hw::device &hwdev);
secret_key generate_keys(public_key &pub, secret_key &sec, hw::device &hwdev);
bool secret_key_to_public_key(const secret_key &sec, public_key &pub, hw::device &hwdev);
bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation, hw::device &hwdev);
void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res, hw::device &hwdev) ;
bool derive_public_key(const key_derivation &derivation, size_t output_index, const public_key &base, public_key &derived_key, hw::device &hwdev);
void derive_secret_key(const key_derivation &derivation, size_t output_index, const secret_key &base, secret_key &derived_key, hw::device &hwdev);
bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &derived_key, hw::device &hwdev);
void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image, hw::device &hwdev);


/* Generate N random bytes
*/
inline void rand(size_t N, uint8_t *bytes) {
Expand All @@ -166,6 +184,9 @@ namespace crypto {
return res;
}

inline void hash_to_ec(const public_key &key, ge_p3 &res) {
crypto_ops::hash_to_ec(key,res);
}
/* Generate a new key pair
*/
inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
Expand Down
79 changes: 79 additions & 0 deletions src/crypto/crypto_device.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2014-2018, The Monero Project
//
// 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.
//


#include "crypto.h"
#include "device/device.hpp"
#include "device/log.hpp"

namespace crypto {

secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover, hw::device &hwdev) {
secret_key rng;
hwdev.generate_keys(pub, sec, recovery_key, recover, rng);
return rng;
}

secret_key generate_keys(public_key &pub, secret_key &sec, hw::device &hwdev) {
secret_key rng;
hwdev.generate_keys(pub, sec, secret_key(), false, rng);
return rng;
}


bool secret_key_to_public_key(const secret_key &sec, public_key &pub, hw::device &hwdev) {
return hwdev.secret_key_to_public_key(sec, pub);
}

bool generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation, hw::device &hwdev) {
return hwdev.generate_key_derivation(key1, key2, derivation);
}

void derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res, hw::device &hwdev) {
hwdev.derivation_to_scalar(derivation, output_index, res);
}

bool derive_public_key(const key_derivation &derivation, size_t output_index,
const public_key &base, public_key &derived_key, hw::device &hwdev) {
return hwdev.derive_public_key(derivation, output_index, base, derived_key);
}

void derive_secret_key(const key_derivation &derivation, size_t output_index,
const secret_key &base, secret_key &derived_key, hw::device &hwdev) {
hwdev.derive_secret_key(derivation, output_index, base, derived_key);
}

bool derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &derived_key, hw::device &hwdev) {
return hwdev.derive_subaddress_public_key(out_key, derivation, output_index, derived_key);
}

void generate_key_image(const public_key &pub, const secret_key &sec, key_image &image, hw::device &hwdev) {
hwdev.generate_key_image(pub,sec,image);
}
}
1 change: 1 addition & 0 deletions src/crypto/hash-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ enum {

void cn_fast_hash(const void *data, size_t length, char *hash);
void cn_slow_hash(const void *data, size_t length, char *hash);
void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool pre);

void hash_extra_blake(const void *data, size_t length, char *hash);
void hash_extra_groestl(const void *data, size_t length, char *hash);
Expand Down
12 changes: 9 additions & 3 deletions src/crypto/slow-hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,8 +515,11 @@ void slow_hash_free_state(void)
* @param length the length in bytes of the data
* @param hash a pointer to a buffer in which the final 256 bit hash will be stored
*/
void cn_slow_hash(const void *data, size_t length, char *hash) {
cn_slow_hash_pre(data,length,hash,false);
}

void cn_slow_hash(const void *data, size_t length, char *hash)
void cn_slow_hash_pre(const void *data, size_t length, char *hash, bool prehashed)
{
RDATA_ALIGN16 uint8_t expandedKey[240]; /* These buffers are aligned to use later with SSE functions */

Expand All @@ -543,8 +546,11 @@ void cn_slow_hash(const void *data, size_t length, char *hash)
slow_hash_allocate_state();

/* CryptoNight Step 1: Use Keccak1600 to initialize the 'state' (and 'text') buffers from the data. */

hash_process(&state.hs, data, length);
if (prehashed) {
memcpy(&state.hs, data, length);
} else {
hash_process(&state.hs, data, length);
}
memcpy(text, state.init, INIT_SIZE_BYTE);

/* CryptoNight Step 2: Iteratively encrypt the results from Keccak to fill
Expand Down
1 change: 1 addition & 0 deletions src/cryptonote_basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ target_link_libraries(cryptonote_basic
common
cncrypto
checkpoints
device
${Boost_DATE_TIME_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_SERIALIZATION_LIBRARY}
Expand Down
40 changes: 40 additions & 0 deletions src/cryptonote_basic/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ extern "C"
}
#include "cryptonote_basic_impl.h"
#include "cryptonote_format_utils.h"
#include "device/device.hpp"

#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "account"
Expand All @@ -50,6 +51,17 @@ DISABLE_VS_WARNINGS(4244 4345)

namespace cryptonote
{

//-----------------------------------------------------------------
hw::device& account_keys::get_device() const {
return *m_device;
}
//-----------------------------------------------------------------
void account_keys::set_device( hw::device &hwdev) {
m_device = &hwdev;
MCDEBUG("device", "account_keys::set_device device type: "<<typeid(hwdev).name());
}

//-----------------------------------------------------------------
account_base::account_base()
{
Expand Down Expand Up @@ -116,6 +128,34 @@ DISABLE_VS_WARNINGS(4244 4345)
if (m_creation_timestamp == (uint64_t)-1) // failure
m_creation_timestamp = 0; // lowest value
}

//-----------------------------------------------------------------
void account_base::create_from_device(const std::string &device_name)
{

hw::device &hwdev = hw::get_device(device_name);
m_keys.set_device(hwdev);
hwdev.set_name(device_name);
MCDEBUG("ledger", "device type: "<<typeid(hwdev).name());
hwdev.init();
hwdev.connect();
hwdev.get_public_address(m_keys.m_account_address);
#ifdef DEBUG_HWDEVICE
hwdev.get_secret_keys(m_keys.m_view_secret_key, m_keys.m_spend_secret_key);
#endif
struct tm timestamp = {0};
timestamp.tm_year = 2014 - 1900; // year 2014
timestamp.tm_mon = 4 - 1; // month april
timestamp.tm_mday = 15; // 15th of april
timestamp.tm_hour = 0;
timestamp.tm_min = 0;
timestamp.tm_sec = 0;

m_creation_timestamp = mktime(&timestamp);
if (m_creation_timestamp == (uint64_t)-1) // failure
m_creation_timestamp = 0; // lowest value
}

//-----------------------------------------------------------------
void account_base::create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey)
{
Expand Down
11 changes: 11 additions & 0 deletions src/cryptonote_basic/account.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "cryptonote_basic.h"
#include "crypto/crypto.h"
#include "serialization/keyvalue_serialization.h"
#include "device/device_declare.hpp"

namespace cryptonote
{
Expand All @@ -43,13 +44,19 @@ namespace cryptonote
crypto::secret_key m_spend_secret_key;
crypto::secret_key m_view_secret_key;
std::vector<crypto::secret_key> m_multisig_keys;
hw::device *m_device = &hw::get_device("default");

BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(m_account_address)
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_spend_secret_key)
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(m_view_secret_key)
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_multisig_keys)
END_KV_SERIALIZE_MAP()

account_keys& operator=(account_keys const&) = default;

hw::device& get_device() const ;
void set_device( hw::device &hwdev) ;
};

/************************************************************************/
Expand All @@ -60,6 +67,7 @@ namespace cryptonote
public:
account_base();
crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false);
void create_from_device(const std::string &device_name) ;
void create_from_keys(const cryptonote::account_public_address& address, const crypto::secret_key& spendkey, const crypto::secret_key& viewkey);
void create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey);
bool make_multisig(const crypto::secret_key &view_secret_key, const crypto::secret_key &spend_secret_key, const crypto::public_key &spend_public_key, const std::vector<crypto::secret_key> &multisig_keys);
Expand All @@ -68,6 +76,9 @@ namespace cryptonote
std::string get_public_address_str(bool testnet) const;
std::string get_public_integrated_address_str(const crypto::hash8 &payment_id, bool testnet) const;

hw::device& get_device() const {return m_keys.get_device();}
void set_device( hw::device &hwdev) {m_keys.set_device(hwdev);}

uint64_t get_createtime() const { return m_creation_timestamp; }
void set_createtime(uint64_t val) { m_creation_timestamp = val; }

Expand Down

0 comments on commit c7ace5f

Please sign in to comment.