Browse Source

PASS1-113: Give the user a way to clear the developer pubkey slot (#25)

PASS1-133
Corey Lakey 4 years ago
committed by Ken Carpenter
parent
commit
f595e0bc24
  1. 14
      ports/stm32/boards/Passport/modfoundation.c
  2. 129
      ports/stm32/boards/Passport/modules/actions.py
  3. 3
      ports/stm32/boards/Passport/modules/common.py
  4. 15
      ports/stm32/boards/Passport/modules/flow.py
  5. 11
      ports/stm32/boards/Passport/modules/utils.py

14
ports/stm32/boards/Passport/modfoundation.c

@ -1388,6 +1388,18 @@ System_get_user_firmware_pubkey(mp_obj_t self, mp_obj_t pubkey)
return mp_const_false;
}
/// def is_user_firmware_installed(self) -> None
/// '''
/// Check if user firmware is installed or not
/// '''
STATIC mp_obj_t
System_is_user_firmware_installed(mp_obj_t self)
{
passport_firmware_header_t* fwhdr = (passport_firmware_header_t*)FW_HDR;
return (fwhdr->signature.pubkey1 == FW_USER_KEY && fwhdr->signature.pubkey2 == 0) ? mp_const_true : mp_const_false;
}
/// def System_supply_chain_challenge(self, challenge, response) -> None
/// '''
/// Perform the supply chain challenge (HMAC)
@ -1572,6 +1584,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(System_sha256_obj, System_sha256);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(System_validate_firmware_header_obj, System_validate_firmware_header);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(System_set_user_firmware_pubkey_obj, System_set_user_firmware_pubkey);
STATIC MP_DEFINE_CONST_FUN_OBJ_2(System_get_user_firmware_pubkey_obj, System_get_user_firmware_pubkey);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(System_is_user_firmware_installed_obj, System_is_user_firmware_installed);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(System_supply_chain_challenge_obj, System_supply_chain_challenge);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(System_hmac_sha256_obj, 4, 4, System_hmac_sha256);
STATIC MP_DEFINE_CONST_FUN_OBJ_3(System_verify_supply_chain_server_signature_obj, System_verify_supply_chain_server_signature);
@ -1603,6 +1616,7 @@ STATIC const mp_rom_map_elem_t System_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_validate_firmware_header), MP_ROM_PTR(&System_validate_firmware_header_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_user_firmware_pubkey), MP_ROM_PTR(&System_set_user_firmware_pubkey_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_user_firmware_pubkey), MP_ROM_PTR(&System_get_user_firmware_pubkey_obj) },
{ MP_ROM_QSTR(MP_QSTR_is_user_firmware_installed), MP_ROM_PTR(&System_is_user_firmware_installed_obj) },
{ MP_ROM_QSTR(MP_QSTR_supply_chain_challenge), MP_ROM_PTR(&System_supply_chain_challenge_obj) },
{ MP_ROM_QSTR(MP_QSTR_verify_supply_chain_server_signature), MP_ROM_PTR(&System_verify_supply_chain_server_signature_obj) },
{ MP_ROM_QSTR(MP_QSTR_hmac_sha256), MP_ROM_PTR(&System_hmac_sha256_obj) },

129
ports/stm32/boards/Passport/modules/actions.py

@ -22,7 +22,8 @@ import common
from common import settings, system, noise, dis
from utils import (UXStateMachine, imported, pretty_short_delay, xfp2str, to_str,
truncate_string_to_width, set_next_addr, scan_for_address, get_accounts, run_chooser,
make_account_name_num, is_valid_address, save_next_addr, needs_microsd, format_btc_address)
make_account_name_num, is_valid_address, save_next_addr, needs_microsd, format_btc_address,
is_all_zero, bytes_to_hex_str, split_to_lines)
from wallets.utils import get_export_mode, get_addr_type_from_address, get_deriv_path_from_addr_type_and_acct
from ux import (the_ux, ux_confirm, ux_enter_pin,
ux_enter_text, ux_scan_qr_code, ux_shutdown,
@ -1396,53 +1397,14 @@ async def handle_psbt_data_format(data):
return False
async def import_user_firmware_pubkey(*a):
from common import system, dis
from ubinascii import hexlify
result = await ux_show_story('''Passport allows you to compile your own firmware version and sign it \
with your private key.
To enable this, you must first import your corresponding public key.
On the next screen, you can select your public key and import it into Passport.''', title='Import PubKey')
if result == 'x':
return
fn = await file_picker('Select public key file (*-pub.bin)', suffix='-pub.bin')
if fn == None:
return
system.turbo(True)
with CardSlot() as card:
with open(fn, 'rb') as fd:
fd.seek(24) # Skip the header
pubkey = fd.read(64) # Read the pubkey
# print('pubkey = {}'.format(hexlify(pubkey)))
result = system.set_user_firmware_pubkey(pubkey)
if result:
dis.fullscreen('Successfully Imported!')
else:
dis.fullscreen('Unable to Import')
await sleep_ms(1000)
# print('system.set_user_firmware_pubkey() = {}'.format(result))
system.turbo(False)
async def read_user_firmware_pubkey(*a):
from common import system
from ubinascii import hexlify
def read_user_firmware_pubkey():
pubkey = bytearray(64)
system.turbo(True)
result = system.get_user_firmware_pubkey(pubkey)
# print('system.get_user_firmware_pubkey() = {}'.format(result))
# print(' len={} pubkey = {}'.format(len(pubkey), hexlify(pubkey)))
system.turbo(False)
return result, pubkey
async def enter_passphrase(menu, label, item):
import sys
@ -1458,7 +1420,6 @@ async def enter_passphrase(menu, label, item):
return
# Applying the passphrase takes a bit of time so show message
from common import dis
dis.fullscreen("Applying Passphrase...")
system.show_busy_bar()
@ -2040,3 +2001,85 @@ async def set_last_verified_addr(*a):
from public_constants import AF_P2WPKH
save_next_addr(0, AF_P2WPKH, 76, False)
def clear_cached_pubkey():
common.cached_pubkey = None
async def install_user_firmware_pubkey(*a):
from ubinascii import hexlify
result = await ux_show_story('''Passport allows you to compile your own firmware version and sign it \
with your private key.
To enable this, you must first import your corresponding public key.
On the next screen, you can select your public key and import it into Passport.''', title='Import PubKey')
if result == 'x':
return
fn = await file_picker('Select public key file (*-pub.bin)', suffix='-pub.bin')
if fn == None:
return
system.turbo(True)
with CardSlot() as card:
with open(fn, 'rb') as fd:
fd.seek(24) # Skip the header
pubkey = fd.read(64) # Read the pubkey
# print('pubkey = {}'.format(hexlify(pubkey)))
result = system.set_user_firmware_pubkey(pubkey)
if result:
await ux_show_story('Successfully Installed!',
title='Install',
center=True,
center_vertically=True)
else:
await ux_show_story('Unable to Install.',
title='Install',
center=True,
center_vertically=True)
clear_cached_pubkey()
# print('system.set_user_firmware_pubkey() = {}'.format(result))
system.turbo(False)
async def view_user_firmware_pubkey(*a):
pubkey_result, pubkey = read_user_firmware_pubkey()
if pubkey_result:
pubkey = bytes_to_hex_str(pubkey)
pubkey = split_to_lines(pubkey, 16)
else:
pubkey = 'Unable to read Developer PubKey'
result = await ux_show_story(pubkey,
title='View PubKey',
center=True,
center_vertically=True)
if result == 'x':
return
async def remove_user_firmware_pubkey(*a):
if system.is_user_firmware_installed():
await ux_show_story('You must install official Foundation firmware before you can remove the Developer PubKey.',
title='Remove',
center=True,
center_vertically=True)
return
pubkey = bytearray(64)
# Confirm the user knows the potential consequences
if await ux_confirm('Are you sure you want to remove the Developer PubKey?', title='Remove'):
result = system.set_user_firmware_pubkey(pubkey)
if result:
await ux_show_story('Successfully Removed PubKey!',
title='Remove',
center=True,
center_vertically=True)
else:
await ux_show_story('Unable to Remove PubKey',
title='Remove',
center=True,
center_vertically=True)
clear_cached_pubkey()

3
ports/stm32/boards/Passport/modules/common.py

@ -67,3 +67,6 @@ is_new_wallet_a_duplicate = False
# The QRTYpe of the last QR code that was scanned
last_scanned_qr_type = None
last_scanned_ur_prefix = None
# Cached Developer PubKey
cached_pubkey = None

15
ports/stm32/boards/Passport/modules/flow.py

@ -45,13 +45,26 @@ def has_secrets():
from common import pa
return not pa.is_secret_blank()
def has_pubkey():
if common.cached_pubkey == None:
result, common.cached_pubkey = read_user_firmware_pubkey()
if not result:
return False
return not is_all_zero(common.cached_pubkey)
DeveloperPubkeyMenu = [
MenuItem('Install PubKey', predicate=lambda: not has_pubkey(), f=install_user_firmware_pubkey),
MenuItem('View PubKey', predicate=has_pubkey, f=view_user_firmware_pubkey),
MenuItem('Remove PubKey', predicate=has_pubkey, f=remove_user_firmware_pubkey)
]
AdvancedMenu = [
MenuItem('Change PIN', f=change_pin),
MenuItem('Passphrase', menu_title='Passphrase', chooser=enable_passphrase_chooser),
MenuItem('Sign Text File', predicate=has_secrets, f=sign_message_on_sd),
MenuItem('MicroSD Settings', menu=SDCardMenu),
MenuItem('View Seed Words', f=view_seed_words, predicate=lambda: settings.get('words', True)),
MenuItem('Developer PubKey', f=import_user_firmware_pubkey),
MenuItem('Developer PubKey', menu=DeveloperPubkeyMenu, menu_title='Developer'),
MenuItem('Erase Passport', f=erase_wallet, arg=True)
]

11
ports/stm32/boards/Passport/modules/utils.py

@ -821,9 +821,18 @@ def format_btc_address(address, addr_type):
else:
width = 16
return '\n'.join([address[i:i+width] for i in range(0, len(address), width)])
return split_to_lines(address, width)
def get_backups_folder_path(card):
return '{}/backups'.format(card.get_sd_root())
def is_all_zero(buf):
for b in buf:
if b != 0:
return False
return True
def split_to_lines(s, width):
return '\n'.join([s[i:i+width] for i in range(0, len(s), width)])
# EOF

Loading…
Cancel
Save