mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-16 11:28:14 +00:00
core/webauthn: Modify error handling to match fido2-tests.
This commit is contained in:
parent
9537bc40a5
commit
4a81101c84
@ -98,6 +98,7 @@ _GETINFO_RESP_VERSIONS = const(0x01) # array of str, required
|
|||||||
_GETINFO_RESP_EXTENSIONS = const(0x02) # array of str, optional
|
_GETINFO_RESP_EXTENSIONS = const(0x02) # array of str, optional
|
||||||
_GETINFO_RESP_AAGUID = const(0x03) # bytes(16), required
|
_GETINFO_RESP_AAGUID = const(0x03) # bytes(16), required
|
||||||
_GETINFO_RESP_OPTIONS = const(0x04) # map, optional
|
_GETINFO_RESP_OPTIONS = const(0x04) # map, optional
|
||||||
|
_GETINFO_RESP_PIN_PROTOCOLS = const(0x06) # list of unsigned integers, optional
|
||||||
|
|
||||||
# CBOR ClientPin command parameter keys
|
# CBOR ClientPin command parameter keys
|
||||||
_CLIENTPIN_CMD_PIN_PROTOCOL = const(0x01) # unsigned int, required
|
_CLIENTPIN_CMD_PIN_PROTOCOL = const(0x01) # unsigned int, required
|
||||||
@ -152,6 +153,7 @@ _ERR_NO_CREDENTIALS = const(0x2E) # no valid credentials provided
|
|||||||
_ERR_NOT_ALLOWED = const(0x30) # continuation command not allowed
|
_ERR_NOT_ALLOWED = const(0x30) # continuation command not allowed
|
||||||
_ERR_PIN_AUTH_INVALID = const(0x33) # pinAuth verification failed
|
_ERR_PIN_AUTH_INVALID = const(0x33) # pinAuth verification failed
|
||||||
_ERR_OTHER = const(0x7F) # other unspecified error
|
_ERR_OTHER = const(0x7F) # other unspecified error
|
||||||
|
_ERR_EXTENSION_FIRST = const(0xE0) # extension specific error
|
||||||
|
|
||||||
# command status responses
|
# command status responses
|
||||||
_SW_NO_ERROR = const(0x9000)
|
_SW_NO_ERROR = const(0x9000)
|
||||||
@ -216,6 +218,11 @@ _USE_BASIC_ATTESTATION = False
|
|||||||
_AUTOCONFIRM = False
|
_AUTOCONFIRM = False
|
||||||
|
|
||||||
|
|
||||||
|
class CborError(Exception):
|
||||||
|
def __init__(self, code: int):
|
||||||
|
self.code = code
|
||||||
|
|
||||||
|
|
||||||
def frame_init() -> dict:
|
def frame_init() -> dict:
|
||||||
# uint32_t cid; // Channel identifier
|
# uint32_t cid; // Channel identifier
|
||||||
# uint8_t cmd; // Command - b7 set
|
# uint8_t cmd; // Command - b7 set
|
||||||
@ -817,6 +824,10 @@ class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
|||||||
self._user_verification,
|
self._user_verification,
|
||||||
)
|
)
|
||||||
cmd = Cmd(self.cid, _CMD_CBOR, bytes([_ERR_NONE]) + response_data)
|
cmd = Cmd(self.cid, _CMD_CBOR, bytes([_ERR_NONE]) + response_data)
|
||||||
|
except CborError as e:
|
||||||
|
cmd = cbor_error(self.cid, e.code)
|
||||||
|
except KeyError:
|
||||||
|
cmd = cbor_error(self.cid, _ERR_MISSING_PARAMETER)
|
||||||
except Exception:
|
except Exception:
|
||||||
cmd = cbor_error(self.cid, _ERR_OPERATION_DENIED)
|
cmd = cbor_error(self.cid, _ERR_OPERATION_DENIED)
|
||||||
|
|
||||||
@ -1580,21 +1591,24 @@ def cbor_get_assertion_hmac_secret(
|
|||||||
cred: Credential, hmac_secret: dict
|
cred: Credential, hmac_secret: dict
|
||||||
) -> Optional[bytes]:
|
) -> Optional[bytes]:
|
||||||
key_agreement = hmac_secret[1] # The public key of platform key agreement key.
|
key_agreement = hmac_secret[1] # The public key of platform key agreement key.
|
||||||
salt_enc = hmac_secret[2] # The encrypted salt.
|
|
||||||
salt_auth = hmac_secret[3] # The HMAC of the encrypted salt.
|
|
||||||
|
|
||||||
x = key_agreement[_COSE_X_COORD_KEY]
|
|
||||||
y = key_agreement[_COSE_Y_COORD_KEY]
|
|
||||||
if (
|
if (
|
||||||
key_agreement[_COSE_ALG_KEY] != _COSE_ALG_ECDH_ES_HKDF_256
|
key_agreement[_COSE_ALG_KEY] != _COSE_ALG_ECDH_ES_HKDF_256
|
||||||
or key_agreement[_COSE_KEY_TYPE_KEY] != _COSE_KEY_TYPE_EC2
|
or key_agreement[_COSE_KEY_TYPE_KEY] != _COSE_KEY_TYPE_EC2
|
||||||
or key_agreement[_COSE_CURVE_KEY] != _COSE_CURVE_P256
|
or key_agreement[_COSE_CURVE_KEY] != _COSE_CURVE_P256
|
||||||
or len(x) != 32
|
):
|
||||||
|
return None
|
||||||
|
|
||||||
|
x = key_agreement[_COSE_X_COORD_KEY]
|
||||||
|
y = key_agreement[_COSE_Y_COORD_KEY]
|
||||||
|
salt_enc = hmac_secret[2] # The encrypted salt.
|
||||||
|
salt_auth = hmac_secret[3] # The HMAC of the encrypted salt.
|
||||||
|
if (
|
||||||
|
len(x) != 32
|
||||||
or len(y) != 32
|
or len(y) != 32
|
||||||
or len(salt_auth) != 16
|
or len(salt_auth) != 16
|
||||||
or len(salt_enc) not in (32, 64)
|
or len(salt_enc) not in (32, 64)
|
||||||
):
|
):
|
||||||
return None
|
raise CborError(_ERR_INVALID_LEN)
|
||||||
|
|
||||||
# Compute the ECDH shared secret.
|
# Compute the ECDH shared secret.
|
||||||
ecdh_result = nist256p1.multiply(_KEY_AGREEMENT_PRIVKEY, b"\04" + x + y)
|
ecdh_result = nist256p1.multiply(_KEY_AGREEMENT_PRIVKEY, b"\04" + x + y)
|
||||||
@ -1603,7 +1617,7 @@ def cbor_get_assertion_hmac_secret(
|
|||||||
# Check the authentication tag and decrypt the salt.
|
# Check the authentication tag and decrypt the salt.
|
||||||
tag = hmac.Hmac(shared_secret, salt_enc, hashlib.sha256).digest()[:16]
|
tag = hmac.Hmac(shared_secret, salt_enc, hashlib.sha256).digest()[:16]
|
||||||
if not utils.consteq(tag, salt_auth):
|
if not utils.consteq(tag, salt_auth):
|
||||||
return None
|
raise CborError(_ERR_EXTENSION_FIRST)
|
||||||
salt = aes(aes.CBC, shared_secret).decrypt(salt_enc)
|
salt = aes(aes.CBC, shared_secret).decrypt(salt_enc)
|
||||||
|
|
||||||
# Get cred_random - a constant symmetric key associated with the credential.
|
# Get cred_random - a constant symmetric key associated with the credential.
|
||||||
@ -1692,6 +1706,7 @@ def cbor_get_info(req: Cmd) -> Cmd:
|
|||||||
"up": True,
|
"up": True,
|
||||||
"uv": True,
|
"uv": True,
|
||||||
},
|
},
|
||||||
|
_GETINFO_RESP_PIN_PROTOCOLS: [1],
|
||||||
}
|
}
|
||||||
return Cmd(req.cid, _CMD_CBOR, bytes([_ERR_NONE]) + cbor.encode(response_data))
|
return Cmd(req.cid, _CMD_CBOR, bytes([_ERR_NONE]) + cbor.encode(response_data))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user