mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-14 01:10:58 +00:00
all: drop XPRV feature of LoadDevice
This commit is contained in:
parent
16af7f1353
commit
fd8aed6105
@ -5,8 +5,6 @@ package hw.trezor.messages.management;
|
|||||||
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
option java_package = "com.satoshilabs.trezor.lib.protobuf";
|
||||||
option java_outer_classname = "TrezorMessageManagement";
|
option java_outer_classname = "TrezorMessageManagement";
|
||||||
|
|
||||||
import "messages-common.proto";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type of the mnemonic backup given/received by the device during reset/recovery.
|
* Type of the mnemonic backup given/received by the device during reset/recovery.
|
||||||
*/
|
*/
|
||||||
@ -216,7 +214,6 @@ message WipeDevice {
|
|||||||
*/
|
*/
|
||||||
message LoadDevice {
|
message LoadDevice {
|
||||||
repeated string mnemonics = 1; // seed encoded as mnemonic (12, 18 or 24 words for BIP39, 20 or 33 for SLIP39)
|
repeated string mnemonics = 1; // seed encoded as mnemonic (12, 18 or 24 words for BIP39, 20 or 33 for SLIP39)
|
||||||
optional hw.trezor.messages.common.HDNodeType node = 2; // BIP-32 node
|
|
||||||
optional string pin = 3; // set PIN protection
|
optional string pin = 3; // set PIN protection
|
||||||
optional bool passphrase_protection = 4; // enable master node encryption using passphrase
|
optional bool passphrase_protection = 4; // enable master node encryption using passphrase
|
||||||
optional string language = 5 [default='english']; // device language
|
optional string language = 5 [default='english']; // device language
|
||||||
|
@ -55,9 +55,6 @@ def _validate(msg) -> int:
|
|||||||
if storage.is_initialized():
|
if storage.is_initialized():
|
||||||
raise wire.UnexpectedMessage("Already initialized")
|
raise wire.UnexpectedMessage("Already initialized")
|
||||||
|
|
||||||
if msg.node is not None:
|
|
||||||
raise wire.ProcessError("LoadDevice.node is not supported")
|
|
||||||
|
|
||||||
if not msg.mnemonics:
|
if not msg.mnemonics:
|
||||||
raise wire.ProcessError("No mnemonic provided")
|
raise wire.ProcessError("No mnemonic provided")
|
||||||
|
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
# fmt: off
|
# fmt: off
|
||||||
import protobuf as p
|
import protobuf as p
|
||||||
|
|
||||||
from .HDNodeType import HDNodeType
|
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
try:
|
try:
|
||||||
from typing import Dict, List # noqa: F401
|
from typing import Dict, List # noqa: F401
|
||||||
@ -18,7 +16,6 @@ class LoadDevice(p.MessageType):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
mnemonics: List[str] = None,
|
mnemonics: List[str] = None,
|
||||||
node: HDNodeType = None,
|
|
||||||
pin: str = None,
|
pin: str = None,
|
||||||
passphrase_protection: bool = None,
|
passphrase_protection: bool = None,
|
||||||
language: str = None,
|
language: str = None,
|
||||||
@ -29,7 +26,6 @@ class LoadDevice(p.MessageType):
|
|||||||
no_backup: bool = None,
|
no_backup: bool = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.mnemonics = mnemonics if mnemonics is not None else []
|
self.mnemonics = mnemonics if mnemonics is not None else []
|
||||||
self.node = node
|
|
||||||
self.pin = pin
|
self.pin = pin
|
||||||
self.passphrase_protection = passphrase_protection
|
self.passphrase_protection = passphrase_protection
|
||||||
self.language = language
|
self.language = language
|
||||||
@ -43,7 +39,6 @@ class LoadDevice(p.MessageType):
|
|||||||
def get_fields(cls) -> Dict:
|
def get_fields(cls) -> Dict:
|
||||||
return {
|
return {
|
||||||
1: ('mnemonics', p.UnicodeType, p.FLAG_REPEATED),
|
1: ('mnemonics', p.UnicodeType, p.FLAG_REPEATED),
|
||||||
2: ('node', HDNodeType, 0),
|
|
||||||
3: ('pin', p.UnicodeType, 0),
|
3: ('pin', p.UnicodeType, 0),
|
||||||
4: ('passphrase_protection', p.BoolType, 0),
|
4: ('passphrase_protection', p.BoolType, 0),
|
||||||
5: ('language', p.UnicodeType, 0), # default=english
|
5: ('language', p.UnicodeType, 0), # default=english
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "messages-common.pb.h"
|
||||||
#include "messages.pb.h"
|
#include "messages.pb.h"
|
||||||
|
|
||||||
#include "aes/aes.h"
|
#include "aes/aes.h"
|
||||||
@ -438,27 +439,6 @@ static void config_compute_u2froot(const char *mnemonic,
|
|||||||
session_clear(false); // invalidate seed cache
|
session_clear(false); // invalidate seed cache
|
||||||
}
|
}
|
||||||
|
|
||||||
static void config_setNode(const HDNodeType *node) {
|
|
||||||
StorageHDNode storageHDNode = {0};
|
|
||||||
memzero(&storageHDNode, sizeof(storageHDNode));
|
|
||||||
|
|
||||||
storageHDNode.depth = node->depth;
|
|
||||||
storageHDNode.fingerprint = node->fingerprint;
|
|
||||||
storageHDNode.child_num = node->child_num;
|
|
||||||
storageHDNode.chain_code.size = 32;
|
|
||||||
memcpy(storageHDNode.chain_code.bytes, node->chain_code.bytes, 32);
|
|
||||||
|
|
||||||
if (node->has_private_key) {
|
|
||||||
storageHDNode.has_private_key = true;
|
|
||||||
storageHDNode.private_key.size = 32;
|
|
||||||
memcpy(storageHDNode.private_key.bytes, node->private_key.bytes, 32);
|
|
||||||
}
|
|
||||||
if (sectrue == storage_set(KEY_NODE, &storageHDNode, sizeof(storageHDNode))) {
|
|
||||||
config_set_bool(KEY_INITIALIZED, true);
|
|
||||||
}
|
|
||||||
memzero(&storageHDNode, sizeof(storageHDNode));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
|
|
||||||
bool config_dumpNode(HDNodeType *node) {
|
bool config_dumpNode(HDNodeType *node) {
|
||||||
@ -500,10 +480,7 @@ void config_loadDevice(const LoadDevice *msg) {
|
|||||||
config_changePin("", msg->pin);
|
config_changePin("", msg->pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg->has_node) {
|
if (msg->mnemonics_count) {
|
||||||
storage_delete(KEY_MNEMONIC);
|
|
||||||
config_setNode(&(msg->node));
|
|
||||||
} else if (msg->mnemonics_count) {
|
|
||||||
storage_delete(KEY_NODE);
|
storage_delete(KEY_NODE);
|
||||||
config_setMnemonic(msg->mnemonics[0]);
|
config_setMnemonic(msg->mnemonics[0]);
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define __CONFIG_H__
|
#define __CONFIG_H__
|
||||||
|
|
||||||
#include "bip32.h"
|
#include "bip32.h"
|
||||||
|
#include "messages-common.pb.h"
|
||||||
#include "messages-management.pb.h"
|
#include "messages-management.pb.h"
|
||||||
|
|
||||||
#define STORAGE_FIELD(TYPE, NAME) \
|
#define STORAGE_FIELD(TYPE, NAME) \
|
||||||
|
@ -456,8 +456,6 @@ def wipe_device(connect, bootloader):
|
|||||||
|
|
||||||
@cli.command(help="Load custom configuration to the device.")
|
@cli.command(help="Load custom configuration to the device.")
|
||||||
@click.option("-m", "--mnemonic", multiple=True)
|
@click.option("-m", "--mnemonic", multiple=True)
|
||||||
@click.option("-e", "--expand", is_flag=True)
|
|
||||||
@click.option("-x", "--xprv")
|
|
||||||
@click.option("-p", "--pin", default="")
|
@click.option("-p", "--pin", default="")
|
||||||
@click.option("-r", "--passphrase-protection", is_flag=True)
|
@click.option("-r", "--passphrase-protection", is_flag=True)
|
||||||
@click.option("-l", "--label", default="")
|
@click.option("-l", "--label", default="")
|
||||||
@ -475,25 +473,17 @@ def load_device(
|
|||||||
ignore_checksum,
|
ignore_checksum,
|
||||||
slip0014,
|
slip0014,
|
||||||
):
|
):
|
||||||
n_args = sum(bool(a) for a in (mnemonic, xprv, slip0014))
|
if slip0014 and mnemonic:
|
||||||
if n_args == 0:
|
raise click.ClickException("Cannot use -s and -m together.")
|
||||||
raise click.ClickException("Please provide a mnemonic or xprv")
|
|
||||||
if n_args > 1:
|
|
||||||
raise click.ClickException("Cannot use mnemonic and xprv together")
|
|
||||||
|
|
||||||
client = connect()
|
client = connect()
|
||||||
|
|
||||||
if xprv:
|
|
||||||
return debuglink.load_device_by_xprv(
|
|
||||||
client, xprv, pin, passphrase_protection, label, "english"
|
|
||||||
)
|
|
||||||
|
|
||||||
if slip0014:
|
if slip0014:
|
||||||
mnemonic = [" ".join(["all"] * 12)]
|
mnemonic = [" ".join(["all"] * 12)]
|
||||||
if not label:
|
if not label:
|
||||||
label = "SLIP-0014"
|
label = "SLIP-0014"
|
||||||
|
|
||||||
return debuglink.load_device_by_mnemonic(
|
return debuglink.load_device(
|
||||||
client,
|
client,
|
||||||
list(mnemonic),
|
list(mnemonic),
|
||||||
pin,
|
pin,
|
||||||
|
@ -19,7 +19,7 @@ from copy import deepcopy
|
|||||||
|
|
||||||
from mnemonic import Mnemonic
|
from mnemonic import Mnemonic
|
||||||
|
|
||||||
from . import messages as proto, protobuf, tools
|
from . import messages as proto, protobuf
|
||||||
from .client import TrezorClient
|
from .client import TrezorClient
|
||||||
from .tools import expect
|
from .tools import expect
|
||||||
|
|
||||||
@ -483,56 +483,6 @@ def load_device_by_mnemonic(
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
@expect(proto.Success, field="message")
|
|
||||||
def load_device_by_xprv(client, xprv, pin, passphrase_protection, label, language):
|
|
||||||
if client.features.initialized:
|
|
||||||
raise RuntimeError(
|
|
||||||
"Device is initialized already. Call wipe_device() and try again."
|
|
||||||
)
|
|
||||||
|
|
||||||
if xprv[0:4] not in ("xprv", "tprv"):
|
|
||||||
raise ValueError("Unknown type of xprv")
|
|
||||||
|
|
||||||
if not 100 < len(xprv) < 112: # yes this is correct in Python
|
|
||||||
raise ValueError("Invalid length of xprv")
|
|
||||||
|
|
||||||
node = proto.HDNodeType()
|
|
||||||
data = tools.b58decode(xprv, None).hex()
|
|
||||||
|
|
||||||
if data[90:92] != "00":
|
|
||||||
raise ValueError("Contain invalid private key")
|
|
||||||
|
|
||||||
checksum = (tools.btc_hash(bytes.fromhex(data[:156]))[:4]).hex()
|
|
||||||
if checksum != data[156:]:
|
|
||||||
raise ValueError("Checksum doesn't match")
|
|
||||||
|
|
||||||
# version 0488ade4
|
|
||||||
# depth 00
|
|
||||||
# fingerprint 00000000
|
|
||||||
# child_num 00000000
|
|
||||||
# chaincode 873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508
|
|
||||||
# privkey 00e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35
|
|
||||||
# checksum e77e9d71
|
|
||||||
|
|
||||||
node.depth = int(data[8:10], 16)
|
|
||||||
node.fingerprint = int(data[10:18], 16)
|
|
||||||
node.child_num = int(data[18:26], 16)
|
|
||||||
node.chain_code = bytes.fromhex(data[26:90])
|
|
||||||
node.private_key = bytes.fromhex(data[92:156]) # skip 0x00 indicating privkey
|
|
||||||
|
|
||||||
resp = client.call(
|
|
||||||
proto.LoadDevice(
|
|
||||||
node=node,
|
|
||||||
pin=pin,
|
|
||||||
passphrase_protection=passphrase_protection,
|
|
||||||
language=language,
|
|
||||||
label=label,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
client.init_device()
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
@expect(proto.Success, field="message")
|
@expect(proto.Success, field="message")
|
||||||
def self_test(client):
|
def self_test(client):
|
||||||
if client.features.bootloader_mode is not True:
|
if client.features.bootloader_mode is not True:
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
# fmt: off
|
# fmt: off
|
||||||
from .. import protobuf as p
|
from .. import protobuf as p
|
||||||
|
|
||||||
from .HDNodeType import HDNodeType
|
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
try:
|
try:
|
||||||
from typing import Dict, List # noqa: F401
|
from typing import Dict, List # noqa: F401
|
||||||
@ -18,7 +16,6 @@ class LoadDevice(p.MessageType):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
mnemonics: List[str] = None,
|
mnemonics: List[str] = None,
|
||||||
node: HDNodeType = None,
|
|
||||||
pin: str = None,
|
pin: str = None,
|
||||||
passphrase_protection: bool = None,
|
passphrase_protection: bool = None,
|
||||||
language: str = None,
|
language: str = None,
|
||||||
@ -29,7 +26,6 @@ class LoadDevice(p.MessageType):
|
|||||||
no_backup: bool = None,
|
no_backup: bool = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.mnemonics = mnemonics if mnemonics is not None else []
|
self.mnemonics = mnemonics if mnemonics is not None else []
|
||||||
self.node = node
|
|
||||||
self.pin = pin
|
self.pin = pin
|
||||||
self.passphrase_protection = passphrase_protection
|
self.passphrase_protection = passphrase_protection
|
||||||
self.language = language
|
self.language = language
|
||||||
@ -43,7 +39,6 @@ class LoadDevice(p.MessageType):
|
|||||||
def get_fields(cls) -> Dict:
|
def get_fields(cls) -> Dict:
|
||||||
return {
|
return {
|
||||||
1: ('mnemonics', p.UnicodeType, p.FLAG_REPEATED),
|
1: ('mnemonics', p.UnicodeType, p.FLAG_REPEATED),
|
||||||
2: ('node', HDNodeType, 0),
|
|
||||||
3: ('pin', p.UnicodeType, 0),
|
3: ('pin', p.UnicodeType, 0),
|
||||||
4: ('passphrase_protection', p.BoolType, 0),
|
4: ('passphrase_protection', p.BoolType, 0),
|
||||||
5: ('language', p.UnicodeType, 0), # default=english
|
5: ('language', p.UnicodeType, 0), # default=english
|
||||||
|
@ -1,58 +0,0 @@
|
|||||||
# This file is part of the Trezor project.
|
|
||||||
#
|
|
||||||
# Copyright (C) 2012-2019 SatoshiLabs and contributors
|
|
||||||
#
|
|
||||||
# This library is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Lesser General Public License version 3
|
|
||||||
# as published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# This library is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Lesser General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the License along with this library.
|
|
||||||
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
from trezorlib import btc, debuglink
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip_t2
|
|
||||||
class TestDeviceLoadXprv:
|
|
||||||
@pytest.mark.setup_client(uninitialized=True)
|
|
||||||
def test_load_device_xprv_1(self, client):
|
|
||||||
debuglink.load_device_by_xprv(
|
|
||||||
client,
|
|
||||||
xprv="xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73",
|
|
||||||
pin="",
|
|
||||||
passphrase_protection=False,
|
|
||||||
label="test",
|
|
||||||
language="english",
|
|
||||||
)
|
|
||||||
|
|
||||||
passphrase_protection = client.debug.read_passphrase_protection()
|
|
||||||
assert passphrase_protection is False
|
|
||||||
|
|
||||||
address = btc.get_address(client, "Bitcoin", [])
|
|
||||||
assert address == "128RdrAkJDmqasgvfRf6MC5VcX4HKqH4mR"
|
|
||||||
|
|
||||||
@pytest.mark.setup_client(uninitialized=True)
|
|
||||||
def test_load_device_xprv_2(self, client):
|
|
||||||
debuglink.load_device_by_xprv(
|
|
||||||
client,
|
|
||||||
xprv="xprv9s21ZrQH143K2JF8RafpqtKiTbsbaxEeUaMnNHsm5o6wCW3z8ySyH4UxFVSfZ8n7ESu7fgir8imbZKLYVBxFPND1pniTZ81vKfd45EHKX73",
|
|
||||||
pin="",
|
|
||||||
passphrase_protection=True,
|
|
||||||
label="test",
|
|
||||||
language="english",
|
|
||||||
)
|
|
||||||
|
|
||||||
client.set_passphrase("passphrase")
|
|
||||||
|
|
||||||
passphrase_protection = client.debug.read_passphrase_protection()
|
|
||||||
assert passphrase_protection is True
|
|
||||||
|
|
||||||
address = btc.get_address(client, "Bitcoin", [])
|
|
||||||
assert address == "1CHUbFa4wTTPYgkYaw2LHSd5D4qJjMU8ri"
|
|
Loading…
Reference in New Issue
Block a user