src/apps/fido_u2f: implement u2f counter

This commit is contained in:
Pavol Rusnak 2018-02-28 18:53:52 +01:00
parent 67d835fd3e
commit c0a0630cba
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
4 changed files with 48 additions and 10 deletions

View File

@ -16,6 +16,7 @@ _USE_PASSPHRASE = const(0x05) # 0x01 or empty
_HOMESCREEN = const(0x06) # bytes _HOMESCREEN = const(0x06) # bytes
_NEEDS_BACKUP = const(0x07) # 0x01 or empty _NEEDS_BACKUP = const(0x07) # 0x01 or empty
_FLAGS = const(0x08) # int _FLAGS = const(0x08) # int
_U2F_COUNTER = const(0x09) # int
def get_device_id() -> str: def get_device_id() -> str:
@ -96,6 +97,20 @@ def set_flags(flags: int) -> None:
config.set(_APP, _FLAGS, flags.to_bytes(4, 'big')) config.set(_APP, _FLAGS, flags.to_bytes(4, 'big'))
def next_u2f_counter() -> int:
b = config.get(_APP, _U2F_COUNTER)
if b is None:
b = 0
else:
b = int.from_bytes(b, 'big') + 1
set_u2f_counter(b)
return b
def set_u2f_counter(cntr: int):
config.set(_APP, _FLAGS, cntr.to_bytes(4, 'big'))
def wipe(): def wipe():
config.wipe() config.wipe()
cache.clear() cache.clear()

View File

@ -15,6 +15,8 @@ from trezor.crypto import hashlib
from trezor.crypto import hmac from trezor.crypto import hmac
from trezor.crypto import random from trezor.crypto import random
from trezor.crypto.curve import nist256p1 from trezor.crypto.curve import nist256p1
from apps.common import storage
_HID_RPT_SIZE = const(64) _HID_RPT_SIZE = const(64)
_CID_BROADCAST = const(0xffffffff) # broadcast channel id _CID_BROADCAST = const(0xffffffff) # broadcast channel id
@ -668,20 +670,12 @@ def msg_authenticate_genkey(app_id: bytes, keyhandle: bytes):
return node return node
# TODO: persistent counter
_authenticate_ctr = 0
def msg_authenticate_sign(challenge: bytes, app_id: bytes, privkey: bytes) -> bytes: def msg_authenticate_sign(challenge: bytes, app_id: bytes, privkey: bytes) -> bytes:
global _authenticate_ctr
flags = bytes([_AUTH_FLAG_TUP]) flags = bytes([_AUTH_FLAG_TUP])
# get next counter # get next counter
ctr = _authenticate_ctr ctr = storage.next_u2f_counter()
ctrbuf = ustruct.pack('>L', ctr) ctrbuf = ustruct.pack('>L', ctr)
_authenticate_ctr += 1
# hash input data together with counter # hash input data together with counter
dig = hashlib.sha256() dig = hashlib.sha256()

View File

@ -1,7 +1,7 @@
from trezor.wire import register, protobuf_workflow from trezor.wire import register, protobuf_workflow
from trezor.utils import unimport from trezor.utils import unimport
from trezor.messages.wire_types import \ from trezor.messages.wire_types import \
LoadDevice, ResetDevice, BackupDevice, WipeDevice, RecoveryDevice, ApplySettings, ApplyFlags, ChangePin LoadDevice, ResetDevice, BackupDevice, WipeDevice, RecoveryDevice, ApplySettings, ApplyFlags, ChangePin, SetU2FCounter
@unimport @unimport
@ -52,6 +52,12 @@ def dispatch_ChangePin(*args, **kwargs):
return change_pin(*args, **kwargs) return change_pin(*args, **kwargs)
@unimport
def dispatch_SetU2FCounter(*args, **kwargs):
from .set_u2f_counter import set_u2f_counter
return set_u2f_counter(*args, **kwargs)
def boot(): def boot():
# only enable LoadDevice in debug builds # only enable LoadDevice in debug builds
if __debug__: if __debug__:
@ -63,3 +69,4 @@ def boot():
register(ApplySettings, protobuf_workflow, dispatch_ApplySettings) register(ApplySettings, protobuf_workflow, dispatch_ApplySettings)
register(ApplyFlags, protobuf_workflow, dispatch_ApplyFlags) register(ApplyFlags, protobuf_workflow, dispatch_ApplyFlags)
register(ChangePin, protobuf_workflow, dispatch_ChangePin) register(ChangePin, protobuf_workflow, dispatch_ChangePin)
register(SetU2FCounter, protobuf_workflow, dispatch_SetU2FCounter)

View File

@ -0,0 +1,22 @@
from trezor import ui, wire
from trezor.messages import ButtonRequestType, FailureType
from trezor.messages.Success import Success
from trezor.ui.text import Text
from apps.common import storage
from apps.common.confirm import require_confirm
async def set_u2f_counter(ctx, msg):
if msg.u2f_counter is None:
raise wire.FailureError(FailureType.ProcessError, 'No value provided provided')
await require_confirm(ctx, Text(
'Set U2F counter', ui.ICON_CONFIG,
'Do you really want to',
'set the U2F counter',
ui.BOLD, 'to %d?' % msg.u2f_counter),
code=ButtonRequestType.ProtectCall)
storage.set_u2f_counter(msg.u2f_counter)
return Success(message='U2F counter set')