authenticator_ctap2_2021/
errors.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5pub use crate::ctap2::commands::{client_pin::PinError, CommandError};
6pub use crate::transport::errors::HIDError;
7use std::fmt;
8use std::io;
9use std::sync::mpsc;
10
11// This composite error type is patterned from Phil Daniels' blog:
12// https://www.philipdaniels.com/blog/2019/defining-rust-error-types/
13
14#[derive(Debug)]
15pub enum UnsupportedOption {
16    MaxPinLength,
17    HmacSecret,
18}
19
20#[derive(Debug)]
21pub enum AuthenticatorError {
22    // Errors from external libraries...
23    Io(io::Error),
24    // Errors raised by us...
25    InvalidRelyingPartyInput,
26    NoConfiguredTransports,
27    Platform,
28    InternalError(String),
29    U2FToken(U2FTokenError),
30    Custom(String),
31    VersionMismatch(&'static str, u32),
32    HIDError(HIDError),
33    CryptoError,
34    PinError(PinError),
35    UnsupportedOption(UnsupportedOption),
36}
37
38impl AuthenticatorError {
39    pub fn as_u2f_errorcode(&self) -> u8 {
40        match *self {
41            AuthenticatorError::U2FToken(ref err) => *err as u8,
42            // TODO: This is somewhat ugly, as we hardcode the error code here, instead of using the
43            // const defined in `u2fhid-capi.h`, which we should.
44            AuthenticatorError::PinError(PinError::PinRequired) => 6u8,
45            AuthenticatorError::PinError(PinError::InvalidPin(_)) => 7u8,
46            AuthenticatorError::PinError(PinError::PinAuthBlocked) => 8u8,
47            AuthenticatorError::PinError(PinError::PinBlocked) => 9u8,
48            _ => U2FTokenError::Unknown as u8,
49        }
50    }
51}
52
53impl std::error::Error for AuthenticatorError {}
54
55impl fmt::Display for AuthenticatorError {
56    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57        match *self {
58            AuthenticatorError::Io(ref err) => err.fmt(f),
59            AuthenticatorError::InvalidRelyingPartyInput => {
60                write!(f, "invalid input from relying party")
61            }
62            AuthenticatorError::NoConfiguredTransports => write!(
63                f,
64                "no transports were configured in the authenticator service"
65            ),
66            AuthenticatorError::Platform => write!(f, "unknown platform error"),
67            AuthenticatorError::InternalError(ref err) => write!(f, "internal error: {}", err),
68            AuthenticatorError::U2FToken(ref err) => {
69                write!(f, "A u2f token error occurred {:?}", err)
70            }
71            AuthenticatorError::Custom(ref err) => write!(f, "A custom error occurred {:?}", err),
72            AuthenticatorError::VersionMismatch(manager, version) => write!(
73                f,
74                "{} expected arguments of version CTAP{}",
75                manager, version
76            ),
77            AuthenticatorError::HIDError(ref e) => write!(f, "Device error: {}", e),
78            AuthenticatorError::CryptoError => {
79                write!(f, "The cryptography implementation encountered an error")
80            }
81            AuthenticatorError::PinError(ref e) => write!(f, "PIN Error: {}", e),
82            AuthenticatorError::UnsupportedOption(ref e) => {
83                write!(f, "Unsupported option: {:?}", e)
84            }
85        }
86    }
87}
88
89impl From<io::Error> for AuthenticatorError {
90    fn from(err: io::Error) -> AuthenticatorError {
91        AuthenticatorError::Io(err)
92    }
93}
94
95impl From<HIDError> for AuthenticatorError {
96    fn from(err: HIDError) -> AuthenticatorError {
97        AuthenticatorError::HIDError(err)
98    }
99}
100
101impl From<CommandError> for AuthenticatorError {
102    fn from(err: CommandError) -> AuthenticatorError {
103        AuthenticatorError::HIDError(HIDError::Command(err))
104    }
105}
106
107impl<T> From<mpsc::SendError<T>> for AuthenticatorError {
108    fn from(err: mpsc::SendError<T>) -> AuthenticatorError {
109        AuthenticatorError::InternalError(err.to_string())
110    }
111}
112
113#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
114pub enum U2FTokenError {
115    Unknown = 1,
116    NotSupported = 2,
117    InvalidState = 3,
118    ConstraintError = 4,
119    NotAllowed = 5,
120}
121
122impl U2FTokenError {
123    fn as_str(&self) -> &str {
124        match *self {
125            U2FTokenError::Unknown => "unknown",
126            U2FTokenError::NotSupported => "not supported",
127            U2FTokenError::InvalidState => "invalid state",
128            U2FTokenError::ConstraintError => "constraint error",
129            U2FTokenError::NotAllowed => "not allowed",
130        }
131    }
132}
133
134impl std::fmt::Display for U2FTokenError {
135    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136        write!(f, "{}", self.as_str())
137    }
138}
139
140impl std::error::Error for U2FTokenError {}