diff --git a/core/.changelog.d/3255.added b/core/.changelog.d/3255.added new file mode 100644 index 0000000000..77f420f8f6 --- /dev/null +++ b/core/.changelog.d/3255.added @@ -0,0 +1 @@ +Implement device authentication for Model R. diff --git a/core/src/all_modules.py b/core/src/all_modules.py index 60ac66b011..e66de0e36a 100644 --- a/core/src/all_modules.py +++ b/core/src/all_modules.py @@ -313,6 +313,8 @@ apps.management.apply_flags import apps.management.apply_flags apps.management.apply_settings import apps.management.apply_settings +apps.management.authenticate_device +import apps.management.authenticate_device apps.management.backup_device import apps.management.backup_device apps.management.backup_types diff --git a/core/src/apps/management/authenticate_device.py b/core/src/apps/management/authenticate_device.py new file mode 100644 index 0000000000..b98428dfd4 --- /dev/null +++ b/core/src/apps/management/authenticate_device.py @@ -0,0 +1,50 @@ +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from trezor.messages import AuthenticateDevice, AuthenticityProof + + +async def authenticate_device(msg: AuthenticateDevice) -> AuthenticityProof: + from trezor import utils, wire + from trezor.crypto import optiga + from trezor.crypto.der import read_length + from trezor.crypto.hashlib import sha256 + from trezor.messages import AuthenticityProof + from trezor.ui.layouts import confirm_action + from trezor.utils import BufferReader + + from apps.common.writers import write_compact_size + + await confirm_action( + "authenticate_device", + "Authenticate device", + description="Do you wish to verify the authenticity of your device?", + ) + + header = b"AuthenticateDevice:" + h = utils.HashWriter(sha256()) + write_compact_size(h, len(header)) + h.extend(header) + write_compact_size(h, len(msg.challenge)) + h.extend(msg.challenge) + + try: + signature = optiga.sign(optiga.DEVICE_ECC_KEY_INDEX, h.get_digest()) + except optiga.SigningInaccessible: + raise wire.ProcessError("Signing inaccessible.") + + certificates = [] + r = BufferReader(optiga.get_certificate(optiga.DEVICE_CERT_INDEX)) + while r.remaining_count() > 0: + cert_begin = r.offset + if r.get() != 0x30: + wire.FirmwareError("Device certificate is corrupted.") + n = read_length(r) + cert_len = r.offset - cert_begin + n + r.seek(cert_begin) + certificates.append(r.read_memoryview(cert_len)) + + return AuthenticityProof( + certificates=certificates, + signature=signature, + ) diff --git a/core/src/apps/workflow_handlers.py b/core/src/apps/workflow_handlers.py index a4951409f4..fd184be6e3 100644 --- a/core/src/apps/workflow_handlers.py +++ b/core/src/apps/workflow_handlers.py @@ -59,6 +59,9 @@ def _find_message_handler_module(msg_type: int) -> str: if utils.USE_SD_CARD and msg_type == MessageType.SdProtect: return "apps.management.sd_protect" + if utils.USE_OPTIGA and msg_type == MessageType.AuthenticateDevice: + return "apps.management.authenticate_device" + # bitcoin if msg_type == MessageType.AuthorizeCoinJoin: return "apps.bitcoin.authorize_coinjoin"