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