示例#1
0
async def get_entropy(ctx, msg):

    text = Text('Confirm entropy')
    text.bold('Do you really want', 'to send entropy?')
    text.normal('Continue only if you', 'know what you are doing!')
    await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall)

    size = min(msg.size, 1024)
    entropy = random.bytes(size)

    return Entropy(entropy=entropy)
示例#2
0
 def test_bytes_uniform(self):
     for _ in range(100):
         c = {}
         for h in '0123456789abcdef':
             c[h] = 0
         for _ in range(8):
             b = random.bytes(1000)
             for h in hexlify(b):
                 c[chr(h)] += 1
         for h in '0123456789abcdef':
             self.assertAlmostEqual(c[h], 1000, delta=200)
示例#3
0
def start_session(received_session_id: bytes = None) -> bytes:
    if received_session_id and received_session_id in _session_ids:
        session_id = received_session_id
    else:
        session_id = random.bytes(32)
        _caches[session_id] = {}

    global _active_session_id
    _active_session_id = session_id
    _move_session_ids_queue(session_id)
    return _active_session_id
示例#4
0
def encrypt(key: bytes, plaintext: bytes, associated_data: bytes | None = None):
    """
    Uses ChaCha20Poly1305 for encryption
    """
    nonce = random.bytes(12)
    cipher = ChaCha20Poly1305(key, nonce)
    if associated_data:
        cipher.auth(associated_data)
    ciphertext = cipher.encrypt(plaintext)
    tag = cipher.finish()
    return nonce, ciphertext + tag, b""
示例#5
0
async def sd_protect_enable(ctx: wire.Context, msg: SdProtect) -> Success:
    salt_auth_key = device.get_sd_salt_auth_key()
    if salt_auth_key is not None:
        raise wire.ProcessError("SD card protection already enabled")

    # Confirm that user wants to proceed with the operation.
    await require_confirm_sd_protect(ctx, msg)

    # Get the current PIN.
    if config.has_pin():
        pin = pin_to_int(await request_pin_ack(ctx, "Enter PIN", config.get_pin_rem()))
    else:
        pin = pin_to_int("")

    # Check PIN and prepare salt file.
    salt = random.bytes(SD_SALT_LEN_BYTES)
    salt_auth_key = random.bytes(SD_SALT_AUTH_KEY_LEN_BYTES)
    salt_tag = hmac.new(salt_auth_key, salt, sha256).digest()[
        :SD_SALT_AUTH_TAG_LEN_BYTES
    ]
    try:
        await set_sd_salt(ctx, salt, salt_tag)
    except Exception:
        raise wire.ProcessError("Failed to write to SD card")

    if not config.change_pin(pin, pin, None, salt):
        # Wrong PIN. Clean up the prepared salt file.
        try:
            await remove_sd_salt(ctx)
        except Exception:
            # The cleanup is not necessary for the correct functioning of
            # SD-protection. If it fails for any reason, we suppress the
            # exception, because primarily we need to raise wire.PinInvalid.
            pass
        await show_pin_invalid(ctx)
        raise wire.PinInvalid("PIN invalid")

    device.set_sd_salt_auth_key(salt_auth_key)

    await show_success(ctx, ("You have successfully", "enabled SD protection."))
    return Success(message="SD card protection enabled")
示例#6
0
async def reset_device(ctx, msg):
    # validate parameters and device state
    if msg.strength not in (128, 192, 256):
        raise wire.ProcessError(
            'Invalid strength (has to be 128, 192 or 256 bits)')
    if storage.is_initialized():
        raise wire.UnexpectedMessage('Already initialized')

    # request new PIN
    if msg.pin_protection:
        newpin = await request_pin_confirm(ctx)
    else:
        newpin = ''

    # generate and display internal entropy
    internal_ent = random.bytes(32)
    if __debug__:
        debug.reset_internal_entropy = internal_ent
    if msg.display_random:
        await show_entropy(ctx, internal_ent)

    # request external entropy and compute mnemonic
    ent_ack = await ctx.call(EntropyRequest(), wire_types.EntropyAck)
    mnemonic = generate_mnemonic(msg.strength, internal_ent, ent_ack.entropy)

    if not msg.skip_backup:
        # require confirmation of the mnemonic safety
        await show_warning(ctx)

        # show mnemonic and require confirmation of a random word
        while True:
            await show_mnemonic(ctx, mnemonic)
            if await check_mnemonic(ctx, mnemonic):
                break
            await show_wrong_entry(ctx)

    # write PIN into storage
    if not config.change_pin(pin_to_int(''), pin_to_int(newpin), None):
        raise wire.ProcessError('Could not change PIN')

    # write settings and mnemonic into storage
    storage.load_settings(label=msg.label,
                          use_passphrase=msg.passphrase_protection)
    storage.load_mnemonic(mnemonic=mnemonic, needs_backup=msg.skip_backup)

    # show success message.  if we skipped backup, it's possible that homescreen
    # is still running, uninterrupted.  restart it to pick up new label.
    if not msg.skip_backup:
        await show_success(ctx)
    else:
        workflow.restartdefault()

    return Success(message='Initialized')
示例#7
0
 def __init__(self, creds: misc.AccountCreds):
     self.state = State.FINISHED
     self.creds = creds
     self.inputs_size = 0
     self.outputs_size = 0
     self.extra_size = 0
     self.dst_amounts = {}
     self.inputs_counter = 0
     self.outputs_counter = 0
     self.extra_counter = 0
     self.random_seed = random.bytes(32) # bcncrypto.cn_fast_hash(b"bcn") #
     self.tx_inputs_stream = bcncrypto.get_keccak()
     self.tx_inputs_hash = None
     self.tx_prefix_stream = bcncrypto.get_keccak()
     self.inputs_amount = 0
     self.dst_amount = 0
     self.change_amount = 0
     self.c0 = None
     self.encryption_key = random.bytes(32) # bcncrypto.cn_fast_hash(b"bcn") #
     self.step_args_hash = None
     self.change_amount = 0
示例#8
0
def _split_secret(threshold, share_count, shared_secret):
    if threshold < 1:
        raise ValueError(
            "The requested threshold ({}) must be a positive integer.".format(threshold)
        )

    if threshold > share_count:
        raise ValueError(
            "The requested threshold ({}) must not exceed the number of shares ({}).".format(
                threshold, share_count
            )
        )

    if share_count > MAX_SHARE_COUNT:
        raise ValueError(
            "The requested number of shares ({}) must not exceed {}.".format(
                share_count, MAX_SHARE_COUNT
            )
        )

    # If the threshold is 1, then the digest of the shared secret is not used.
    if threshold == 1:
        return [(i, shared_secret) for i in range(share_count)]

    random_share_count = threshold - 2

    shares = [(i, random.bytes(len(shared_secret))) for i in range(random_share_count)]

    random_part = random.bytes(len(shared_secret) - _DIGEST_LENGTH_BYTES)
    digest = _create_digest(random_part, shared_secret)

    base_shares = shares + [
        (_DIGEST_INDEX, digest + random_part),
        (_SECRET_INDEX, shared_secret),
    ]

    for i in range(random_share_count, share_count):
        shares.append((i, shamir.interpolate(base_shares, i)))

    return shares
示例#9
0
async def layout_reset_device(session_id, msg):
    from trezor.ui.text import Text
    from trezor.crypto import hashlib, random, bip39
    from trezor.messages.EntropyRequest import EntropyRequest
    from trezor.messages.Success import Success
    from trezor.messages import FailureType
    from trezor.messages import ButtonRequestType
    from trezor.messages.wire_types import EntropyAck

    from apps.common.request_pin import request_pin_twice
    from apps.common.confirm import require_confirm
    from apps.common import storage

    if __debug__:
        global internal_entropy

    if msg.strength not in (128, 192, 256):
        raise wire.FailureError(
            FailureType.Other, 'Invalid strength (has to be 128, 192 or 256 bits)')

    if storage.is_initialized():
        raise wire.FailureError(
            FailureType.UnexpectedMessage, 'Already initialized')

    internal_entropy = random.bytes(32)

    if msg.display_random:
        entropy_lines = chunks(ubinascii.hexlify(internal_entropy), 16)
        entropy_content = Text('Internal entropy', ui.ICON_RESET, *entropy_lines)
        await require_confirm(session_id, entropy_content, ButtonRequestType.ResetDevice)

    if msg.pin_protection:
        pin = await request_pin_twice(session_id)
    else:
        pin = None

    external_entropy_ack = await wire.call(session_id, EntropyRequest(), EntropyAck)
    ctx = hashlib.sha256()
    ctx.update(internal_entropy)
    ctx.update(external_entropy_ack.entropy)
    entropy = ctx.digest()
    mnemonic = bip39.from_data(entropy[:msg.strength // 8])

    await show_mnemonic_by_word(session_id, mnemonic)

    storage.load_mnemonic(mnemonic)
    storage.load_settings(pin=pin,
                          passphrase_protection=msg.passphrase_protection,
                          language=msg.language,
                          label=msg.label)

    return Success(message='Initialized')
示例#10
0
async def sd_protect_refresh(ctx: wire.Context, msg: SdProtect) -> Success:
    if device.get_sd_salt_auth_key() is None:
        raise wire.ProcessError("SD card protection not enabled")

    # Confirm that user wants to proceed with the operation.
    await require_confirm_sd_protect(ctx, msg)

    # Get the current PIN and salt from the SD card.
    pin, old_salt = await request_pin_and_sd_salt(ctx, "Enter PIN")

    # Check PIN and change salt.
    new_salt = random.bytes(SD_SALT_LEN_BYTES)
    new_salt_auth_key = random.bytes(SD_SALT_AUTH_KEY_LEN_BYTES)
    new_salt_tag = hmac.new(new_salt_auth_key, new_salt,
                            sha256).digest()[:SD_SALT_AUTH_TAG_LEN_BYTES]
    try:
        await stage_sd_salt(ctx, new_salt, new_salt_tag)
    except Exception:
        raise wire.ProcessError("Failed to write to SD card")

    if not config.change_pin(pin_to_int(pin), pin_to_int(pin), old_salt,
                             new_salt):
        await show_pin_invalid(ctx)
        raise wire.PinInvalid("PIN invalid")

    device.set_sd_salt_auth_key(new_salt_auth_key)

    try:
        # Clean up.
        await commit_sd_salt(ctx)
    except Exception:
        # If the cleanup fails, then request_sd_salt() will bring the SD card
        # into a consistent state. We suppress the exception, because overall
        # SD-protection was successfully refreshed.
        pass

    await show_success(ctx,
                       ("You have successfully", "refreshed SD protection."))
    return Success(message="SD card protection refreshed")
示例#11
0
def get_state(prev_state: bytes = None, passphrase: str = None) -> Optional[bytes]:
    if prev_state is None:
        salt = random.bytes(32)  # generate a random salt if no state provided
    else:
        salt = prev_state[:32]  # use salt from provided state
        if len(salt) != 32:
            return None  # invalid state
    if passphrase is None:
        if _cached_passphrase is None:
            return None  # we don't have any passphrase to compute the state
        else:
            passphrase = _cached_passphrase  # use cached passphrase
    return _compute_state(salt, passphrase)
示例#12
0
async def get_entropy(ctx, msg):

    await require_confirm(ctx,
                          Text('Confirm entropy', ui.ICON_DEFAULT, ui.BOLD,
                               'Do you really want', 'to send entropy?',
                               ui.NORMAL, 'Continue only if you',
                               'know what you are doing!'),
                          code=ButtonRequestType.ProtectCall)

    size = min(msg.size, 1024)
    entropy = random.bytes(size)

    return Entropy(entropy=entropy)
示例#13
0
async def get_entropy(ctx: Context, msg: GetEntropy) -> Entropy:
    await confirm_action(
        ctx,
        "get_entropy",
        "Confirm entropy",
        action="Do you really want\nto send entropy?",
        description="Continue only if you\nknow what you are doing!",
        br_code=ButtonRequestType.ProtectCall,
    )

    size = min(msg.size, 1024)
    entropy = random.bytes(size)

    return Entropy(entropy=entropy)
 def test_lock(self):
     for _ in range(128):
         config.init()
         config.wipe()
         self.assertEqual(config.unlock(pin_to_int('')), True)
         appid, key = random_entry()
         value = random.bytes(16)
         config.set(appid, key, value)
         config.init()
         self.assertEqual(config.get(appid, key), None)
         with self.assertRaises(RuntimeError):
             config.set(appid, key, bytes())
     config.init()
     config.wipe()
示例#15
0
def get_state(state: bytes = None, passphrase: str = None):

    if state is None:
        salt = random.bytes(32)  # generate a random salt if no state provided
    else:
        salt = state[:32]  # use salt from provided state

    if passphrase is None:
        global _passphrase
        if _passphrase is None:
            return None
        passphrase = _passphrase  # use cached passphrase

    # state = HMAC(passphrase, salt || device_id)
    msg = salt + storage.get_device_id().encode()
    state = hmac.new(passphrase.encode(), msg, hashlib.sha256).digest()

    return salt + state
示例#16
0
def get_state(salt: bytes = None, passphrase: str = None):
    global _passphrase, _state_salt
    if salt is None:
        # generate a random salt if not provided and not already cached
        if _state_salt is None:
            _state_salt = random.bytes(32)
    else:
        # otherwise copy provided salt to cached salt
        _state_salt = salt

    # state = HMAC(passphrase, salt || device_id)
    if passphrase is None:
        key = _passphrase if _passphrase is not None else ''
    else:
        key = passphrase
    msg = _state_salt + storage.get_device_id().encode()
    state = hmac.new(key.encode(), msg, hashlib.sha256).digest()

    return _state_salt + state
示例#17
0
def generate_mnemonics_random(
    group_threshold, groups, strength_bits=128, passphrase=b"", iteration_exponent=0
):
    """
    Generates a random master secret and splits it into mnemonic shares using Shamir's secret
    sharing scheme.
    :param int group_threshold: The number of groups required to reconstruct the master secret.
    :param groups: A list of (member_threshold, member_count) pairs for each group, where member_count
        is the number of shares to generate for the group and member_threshold is the number of members required to
        reconstruct the group secret.
    :type groups: List of pairs of integers.
    :param int strength_bits: The entropy of the randomly generated master secret in bits.
    :param passphrase: The passphrase used to encrypt the master secret.
    :type passphrase: Array of bytes.
    :param int iteration_exponent: The iteration exponent.
    :return: List of mnemonics.
    :rtype: List of byte arrays.
    """

    if strength_bits < MIN_STRENGTH_BITS:
        raise ValueError(
            "The requested strength of the master secret ({} bits) must be at least {} bits.".format(
                strength_bits, MIN_STRENGTH_BITS
            )
        )

    if strength_bits % 16 != 0:
        raise ValueError(
            "The requested strength of the master secret ({} bits) must be a multiple of 16 bits.".format(
                strength_bits
            )
        )

    return generate_mnemonics(
        group_threshold,
        groups,
        random.bytes(strength_bits // 8),
        passphrase,
        iteration_exponent,
    )
示例#18
0
async def load_device(ctx, msg):
    word_count = _validate(msg)
    is_slip39 = backup_types.is_slip39_word_count(word_count)

    if not is_slip39 and not msg.skip_checksum and not bip39.check(
            msg.mnemonics[0]):
        raise wire.ProcessError("Mnemonic is not valid")

    await _warn(ctx)

    if not is_slip39:  # BIP-39
        secret = msg.mnemonics[0].encode()
        backup_type = BackupType.Bip39
    else:
        identifier, iteration_exponent, secret, group_count = slip39.combine_mnemonics(
            msg.mnemonics)
        if group_count == 1:
            backup_type = BackupType.Slip39_Basic
        elif group_count > 1:
            backup_type = BackupType.Slip39_Advanced
        else:
            raise RuntimeError("Invalid group count")
        storage.device.set_slip39_identifier(identifier)
        storage.device.set_slip39_iteration_exponent(iteration_exponent)

    storage.device.store_mnemonic_secret(secret,
                                         backup_type,
                                         needs_backup=True,
                                         no_backup=False)
    storage.device.load_settings(use_passphrase=msg.passphrase_protection,
                                 label=msg.label)
    if msg.pin:
        config.change_pin(pin_to_int(""), pin_to_int(msg.pin), None, None)

    beam_nonce_seed = random.bytes(32)
    create_beam_master_nonce(beam_nonce_seed)

    return Success(message="Device loaded")
示例#19
0
    def generate_id(self) -> None:
        self._creation_time = storage.device.next_u2f_counter() or 0

        data = cbor.encode({
            key: value
            for key, value in (
                (_CRED_ID_RP_ID, self.rp_id),
                (_CRED_ID_RP_NAME, self.rp_name),
                (_CRED_ID_USER_ID, self.user_id),
                (_CRED_ID_USER_NAME, self.user_name),
                (_CRED_ID_USER_DISPLAY_NAME, self.user_display_name),
                (_CRED_ID_CREATION_TIME, self._creation_time),
                (_CRED_ID_HMAC_SECRET, self.hmac_secret),
            ) if value
        })
        key = seed.derive_slip21_node_without_passphrase(
            [b"SLIP-0022", _CRED_ID_VERSION, b"Encryption key"]).key()
        iv = random.bytes(12)
        ctx = chacha20poly1305(key, iv)
        ctx.auth(self.rp_id_hash)
        ciphertext = ctx.encrypt(data)
        tag = ctx.finish()
        self.id = _CRED_ID_VERSION + iv + ciphertext + tag
    def generate_id(self) -> None:
        self.creation_time = storage.device.next_u2f_counter() or 0

        if not self.check_required_fields():
            raise AssertionError

        data = {
            key: value
            for key, value in (
                (_CRED_ID_RP_ID, self.rp_id),
                (_CRED_ID_RP_NAME, self.rp_name),
                (_CRED_ID_USER_ID, self.user_id),
                (_CRED_ID_USER_NAME, self.user_name),
                (_CRED_ID_USER_DISPLAY_NAME, self.user_display_name),
                (_CRED_ID_CREATION_TIME, self.creation_time),
                (_CRED_ID_HMAC_SECRET, self.hmac_secret),
                (_CRED_ID_USE_SIGN_COUNT, self.use_sign_count),
            )
            if value
        }

        if self.algorithm != _DEFAULT_ALGORITHM or self.curve != _DEFAULT_CURVE:
            data[_CRED_ID_ALGORITHM] = self.algorithm
            data[_CRED_ID_CURVE] = self.curve

        key = seed.derive_slip21_node_without_passphrase(
            [b"SLIP-0022", _CRED_ID_VERSION, b"Encryption key"]
        ).key()
        iv = random.bytes(12)
        ctx = chacha20poly1305(key, iv)
        ctx.auth(self.rp_id_hash)
        ciphertext = ctx.encrypt(cbor.encode(data))
        tag = ctx.finish()
        self.id = _CRED_ID_VERSION + iv + ciphertext + tag

        if len(self.id) > CRED_ID_MAX_LENGTH:
            raise AssertionError
示例#21
0
def _encrypt(node, public_key: bytes, payload: bytes) -> bytes:
    salt = random.bytes(NEM_SALT_SIZE)
    iv = random.bytes(AES_BLOCK_SIZE)
    encrypted = node.nem_encrypt(public_key, iv, salt, payload)
    return iv + salt + encrypted
示例#22
0
def generate_random_identifier() -> int:
    """Returns a randomly generated integer in the range 0, ... , 2**_ID_LENGTH_BITS - 1."""

    identifier = int.from_bytes(random.bytes(_bits_to_bytes(_ID_LENGTH_BITS)),
                                "big")
    return identifier & ((1 << _ID_LENGTH_BITS) - 1)
示例#23
0
def _make_salt() -> Tuple[bytes, bytes, bytes]:
    salt = random.bytes(storage.sd_salt.SD_SALT_LEN_BYTES)
    auth_key = random.bytes(storage.device.SD_SALT_AUTH_KEY_LEN_BYTES)
    tag = storage.sd_salt.compute_auth_tag(salt, auth_key)
    return salt, auth_key, tag
示例#24
0
async def get_nonce(ctx: wire.Context, msg: GetNonce) -> Nonce:
    nonce = random.bytes(32)
    cache.set(cache.APP_COMMON_NONCE, nonce)
    return Nonce(nonce=nonce)
示例#25
0
async def reset_device(ctx: wire.Context, msg: ResetDevice) -> Success:
    # validate parameters and device state
    _validate_reset_device(msg)

    # make sure user knows they're setting up a new wallet
    if msg.backup_type == BackupType.Slip39_Basic:
        prompt = "Create a new wallet\nwith Shamir Backup?"
    elif msg.backup_type == BackupType.Slip39_Advanced:
        prompt = "Create a new wallet\nwith Super Shamir?"
    else:
        prompt = "Do you want to create\na new wallet?"
    await confirm_reset_device(ctx, prompt)
    await LoadingAnimation()

    # wipe storage to make sure the device is in a clear state
    storage.reset()

    # request and set new PIN
    if msg.pin_protection:
        newpin = await request_pin_confirm(ctx)
        if not config.change_pin("", newpin, None, None):
            raise wire.ProcessError("Failed to set PIN")

    # generate and display internal entropy
    int_entropy = random.bytes(32)
    if __debug__:
        debug.reset_internal_entropy = int_entropy
    if msg.display_random:
        await layout.show_internal_entropy(ctx, int_entropy)

    # request external entropy and compute the master secret
    entropy_ack = await ctx.call(EntropyRequest(), EntropyAck)
    ext_entropy = entropy_ack.entropy
    # For SLIP-39 this is the Encrypted Master Secret
    secret = _compute_secret_from_entropy(int_entropy, ext_entropy, msg.strength)

    # Check backup type, perform type-specific handling
    if msg.backup_type == BackupType.Bip39:
        # in BIP-39 we store mnemonic string instead of the secret
        secret = bip39.from_data(secret).encode()
    elif msg.backup_type in (BackupType.Slip39_Basic, BackupType.Slip39_Advanced):
        # generate and set SLIP39 parameters
        storage.device.set_slip39_identifier(slip39.generate_random_identifier())
        storage.device.set_slip39_iteration_exponent(slip39.DEFAULT_ITERATION_EXPONENT)
    else:
        # Unknown backup type.
        raise RuntimeError

    # If either of skip_backup or no_backup is specified, we are not doing backup now.
    # Otherwise, we try to do it.
    perform_backup = not msg.no_backup and not msg.skip_backup

    # If doing backup, ask the user to confirm.
    if perform_backup:
        perform_backup = await confirm_backup(ctx)

    # generate and display backup information for the master secret
    if perform_backup:
        await backup_seed(ctx, msg.backup_type, secret)

    # write settings and master secret into storage
    if msg.label is not None:
        storage.device.set_label(msg.label)
    storage.device.set_passphrase_enabled(bool(msg.passphrase_protection))
    storage.device.store_mnemonic_secret(
        secret,  # for SLIP-39, this is the EMS
        msg.backup_type,
        needs_backup=not perform_backup,
        no_backup=msg.no_backup,
    )

    # if we backed up the wallet, show success message
    if perform_backup:
        await layout.show_backup_success(ctx)

    return Success(message="Initialized")
示例#26
0
def _new_device_id() -> str:
    return hexlify(random.bytes(12)).decode().upper()
def _protect_signature(state: State, mg_buffer: list[bytes]) -> list[bytes]:
    """
    Encrypts the signature with keys derived from state.opening_key.
    After protocol finishes without error, opening_key is sent to the
    host.
    """
    from trezor.crypto import random
    from trezor.crypto import chacha20poly1305
    from apps.monero.signing import offloading_keys

    if state.last_step != state.STEP_SIGN:
        state.opening_key = random.bytes(32)

    nonce = offloading_keys.key_signature(state.opening_key,
                                          state.current_input_index, True)[:12]

    key = offloading_keys.key_signature(state.opening_key,
                                        state.current_input_index, False)

    cipher = chacha20poly1305(key, nonce)

    # cipher.update() input has to be 512 bit long (besides the last block).
    # Thus we go over mg_buffer and buffer 512 bit input blocks before
    # calling cipher.update().
    CHACHA_BLOCK = 64  # 512 bit chacha key-stream block size
    buff = bytearray(CHACHA_BLOCK)
    buff_len = 0  # valid bytes in the block buffer

    mg_len = 0
    for data in mg_buffer:
        mg_len += len(data)

    # Preallocate array of ciphertext blocks, ceil, add tag block
    mg_res = [None] * (1 + (mg_len + CHACHA_BLOCK - 1) // CHACHA_BLOCK)
    mg_res_c = 0
    for ix, data in enumerate(mg_buffer):
        data_ln = len(data)
        data_off = 0
        while data_ln > 0:
            to_add = min(CHACHA_BLOCK - buff_len, data_ln)
            if to_add:
                buff[buff_len:buff_len + to_add] = data[data_off:data_off +
                                                        to_add]
                data_ln -= to_add
                buff_len += to_add
                data_off += to_add

            if len(buff) != CHACHA_BLOCK or buff_len > CHACHA_BLOCK:
                raise ValueError("Invariant error")

            if buff_len == CHACHA_BLOCK:
                mg_res[mg_res_c] = cipher.encrypt(buff)
                mg_res_c += 1
                buff_len = 0

        mg_buffer[ix] = None
        if ix & 7 == 0:
            gc.collect()

    # The last block can be incomplete
    if buff_len:
        mg_res[mg_res_c] = cipher.encrypt(buff[:buff_len])
        mg_res_c += 1

    mg_res[mg_res_c] = cipher.finish()
    return mg_res
示例#28
0
async def reset_device(ctx, msg):
    if __debug__:
        global internal_entropy

    # validate parameters and device state
    if msg.strength not in (128, 192, 256):
        raise wire.FailureError(
            FailureType.ProcessError,
            'Invalid strength (has to be 128, 192 or 256 bits)')
    if storage.is_initialized():
        raise wire.FailureError(
            FailureType.UnexpectedMessage,
            'Already initialized')

    if msg.pin_protection:
        # request new PIN
        newpin = await request_pin_confirm(ctx)
    else:
        # new PIN is empty
        newpin = ''

    # generate and display internal entropy
    internal_entropy = random.bytes(32)
    if msg.display_random:
        await show_entropy(ctx, internal_entropy)

    # request external entropy and compute mnemonic
    ack = await ctx.call(EntropyRequest(), wire_types.EntropyAck)
    mnemonic = generate_mnemonic(
        msg.strength, internal_entropy, ack.entropy)

    if msg.skip_backup:
        # let user backup the mnemonic later
        pass
    else:
        # warn user about mnemonic safety
        await show_warning(ctx)
        while True:
            # show mnemonic and require confirmation of a random word
            await show_mnemonic(ctx, mnemonic)
            if await check_mnemonic(ctx, mnemonic):
                break
            await show_wrong_entry(ctx)

    # write PIN into storage
    if not config.change_pin(pin_to_int(''), pin_to_int(newpin), None):
        raise wire.FailureError(
            FailureType.ProcessError, 'Could not change PIN')

    # write settings and mnemonic into storage
    storage.load_settings(
        label=msg.label, use_passphrase=msg.passphrase_protection)
    storage.load_mnemonic(
        mnemonic=mnemonic, needs_backup=msg.skip_backup)

    # show success message
    if not msg.skip_backup:
        await show_success(ctx)
    else:
        # trigger reload of homescreen
        workflow.restartdefault()

    return Success(message='Initialized')
示例#29
0
async def reset_device(ctx, msg):
    # validate parameters and device state
    if msg.strength not in (128, 192, 256):
        raise wire.ProcessError(
            "Invalid strength (has to be 128, 192 or 256 bits)")
    if msg.display_random and (msg.skip_backup or msg.no_backup):
        raise wire.ProcessError(
            "Can't show internal entropy when backup is skipped")
    if storage.is_initialized():
        raise wire.UnexpectedMessage("Already initialized")

    text = Text("Create a new wallet", ui.ICON_RESET)
    text.normal("Do you really want to", "create a new wallet?", "")

    await require_confirm(ctx, text, code=ButtonRequestType.ResetDevice)

    # request new PIN
    if msg.pin_protection:
        newpin = await request_pin_confirm(ctx)
    else:
        newpin = ""

    # generate and display internal entropy
    internal_ent = random.bytes(32)
    if __debug__:
        debug.reset_internal_entropy = internal_ent
    if msg.display_random:
        await show_entropy(ctx, internal_ent)

    # request external entropy and compute mnemonic
    ent_ack = await ctx.call(EntropyRequest(), MessageType.EntropyAck)
    mnemonic = generate_mnemonic(msg.strength, internal_ent, ent_ack.entropy)

    if not msg.skip_backup and not msg.no_backup:
        # require confirmation of the mnemonic safety
        await show_warning(ctx)

        # show mnemonic and require confirmation of a random word
        while True:
            await show_mnemonic(ctx, mnemonic)
            if await check_mnemonic(ctx, mnemonic):
                break
            await show_wrong_entry(ctx)

    # write PIN into storage
    if not config.change_pin(pin_to_int(""), pin_to_int(newpin), None):
        raise wire.ProcessError("Could not change PIN")

    # write settings and mnemonic into storage
    storage.load_settings(label=msg.label,
                          use_passphrase=msg.passphrase_protection)
    storage.load_mnemonic(mnemonic=mnemonic,
                          needs_backup=msg.skip_backup,
                          no_backup=msg.no_backup)

    # show success message.  if we skipped backup, it's possible that homescreen
    # is still running, uninterrupted.  restart it to pick up new label.
    if not msg.skip_backup and not msg.no_backup:
        await show_success(ctx)
    else:
        workflow.restartdefault()

    return Success(message="Initialized")
示例#30
0
async def reset_device(ctx: wire.Context, msg: ResetDevice) -> Success:
    # validate parameters and device state
    _validate_reset_device(msg)

    is_slip39_simple = msg.backup_type == ResetDeviceBackupType.Slip39_Single_Group

    # make sure user knows he's setting up a new wallet
    await _show_reset_device_warning(ctx, is_slip39_simple)

    # request new PIN
    if msg.pin_protection:
        newpin = await request_pin_confirm(ctx)
    else:
        newpin = ""

    # generate and display internal entropy
    int_entropy = random.bytes(32)
    if __debug__:
        debug.reset_internal_entropy = int_entropy
    if msg.display_random:
        await layout.show_internal_entropy(ctx, int_entropy)

    # request external entropy and compute the master secret
    entropy_ack = await ctx.call(EntropyRequest(), EntropyAck)
    ext_entropy = entropy_ack.entropy
    # For SLIP-39 this is the Encrypted Master Secret
    secret = _compute_secret_from_entropy(int_entropy, ext_entropy,
                                          msg.strength)

    if is_slip39_simple:
        storage.device.set_slip39_identifier(
            slip39.generate_random_identifier())
        storage.device.set_slip39_iteration_exponent(
            slip39.DEFAULT_ITERATION_EXPONENT)

    # should we back up the wallet now?
    if not msg.no_backup and not msg.skip_backup:
        if not await layout.confirm_backup(ctx):
            if not await layout.confirm_backup_again(ctx):
                msg.skip_backup = True

    # generate and display backup information for the master secret
    if not msg.no_backup and not msg.skip_backup:
        if is_slip39_simple:
            await backup_slip39_wallet(ctx, secret)
        else:
            await backup_bip39_wallet(ctx, secret)

    # write PIN into storage
    if not config.change_pin(pin_to_int(""), pin_to_int(newpin)):
        raise wire.ProcessError("Could not change PIN")

    # write settings and master secret into storage
    storage.device.load_settings(label=msg.label,
                                 use_passphrase=msg.passphrase_protection)
    if is_slip39_simple:
        storage.device.store_mnemonic_secret(
            secret,  # this is the EMS in SLIP-39 terminology
            mnemonic.TYPE_SLIP39,
            needs_backup=msg.skip_backup,
            no_backup=msg.no_backup,
        )
    else:
        # in BIP-39 we store mnemonic string instead of the secret
        storage.device.store_mnemonic_secret(
            bip39.from_data(secret).encode(),
            mnemonic.TYPE_BIP39,
            needs_backup=msg.skip_backup,
            no_backup=msg.no_backup,
        )

    # if we backed up the wallet, show success message
    if not msg.no_backup and not msg.skip_backup:
        await layout.show_backup_success(ctx)

    return Success(message="Initialized")