core/storage: Implement storage of FIDO2 resident credentials.

pull/394/head
Andrew Kozlik 5 years ago
parent de183849b9
commit 6366f3ac0d

@ -9,6 +9,7 @@ if False:
_APP_DEVICE = 0x01
_APP_RECOVERY = 0x02
_APP_RECOVERY_SHARES = 0x03
_APP_FIDO2 = 0x04
# fmt: on
_FALSE_BYTE = b"\x00"

@ -0,0 +1,78 @@
from micropython import const
from apps.common.storage import common
from apps.webauthn.credential import Credential, Fido2Credential
if False:
from typing import List, Optional
_RESIDENT_CREDENTIAL_START_KEY = const(1)
_MAX_RESIDENT_CREDENTIALS = const(16)
def get_resident_credentials(rp_id_hash: Optional[bytes]) -> List[Credential]:
creds = [] # type: List[Credential]
for i in range(
_RESIDENT_CREDENTIAL_START_KEY,
_RESIDENT_CREDENTIAL_START_KEY + _MAX_RESIDENT_CREDENTIALS,
):
stored_cred_data = common._get(common._APP_FIDO2, i)
if stored_cred_data is None:
continue
stored_rp_id_hash = stored_cred_data[:32]
stored_cred_id = stored_cred_data[32:]
if rp_id_hash is not None and rp_id_hash != stored_rp_id_hash:
# Stored credential is not for this RP ID.
continue
stored_cred = Fido2Credential.from_cred_id(stored_cred_id, stored_rp_id_hash)
if stored_cred is not None:
creds.append(stored_cred)
return creds
def store_resident_credential(cred: Fido2Credential) -> bool:
slot = None
for i in range(
_RESIDENT_CREDENTIAL_START_KEY,
_RESIDENT_CREDENTIAL_START_KEY + _MAX_RESIDENT_CREDENTIALS,
):
stored_cred_data = common._get(common._APP_FIDO2, i)
if stored_cred_data is None:
if slot is None:
slot = i
continue
stored_rp_id_hash = stored_cred_data[:32]
stored_cred_id = stored_cred_data[32:]
if cred.rp_id_hash != stored_rp_id_hash:
# Stored credential is not for this RP ID.
continue
stored_cred = Fido2Credential.from_cred_id(stored_cred_id, stored_rp_id_hash)
if stored_cred is None:
# Stored credential is not for this RP ID.
continue
# If a credential for the same RP ID and user ID already exists, then overwrite it.
if stored_cred.user_id == cred.user_id:
slot = i
break
if slot is None:
return False
common._set(common._APP_FIDO2, slot, cred.rp_id_hash + cred.id)
return True
def erase_resident_credentials() -> None:
for i in range(
_RESIDENT_CREDENTIAL_START_KEY,
_RESIDENT_CREDENTIAL_START_KEY + _MAX_RESIDENT_CREDENTIALS,
):
common._delete(common._APP_FIDO2, i)
Loading…
Cancel
Save