opaque_ke/
errors.rs

1// Copyright (c) Meta Platforms, Inc. and affiliates.
2//
3// This source code is dual-licensed under either the MIT license found in the
4// LICENSE-MIT file in the root directory of this source tree or the Apache
5// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
6// of this source tree. You may select, at your option, one of the above-listed
7// licenses.
8
9//! A list of error types which are produced during an execution of the protocol
10use core::convert::Infallible;
11use core::error::Error;
12use core::fmt::Debug;
13
14use displaydoc::Display;
15
16/// Represents an error in the manipulation of internal cryptographic data
17#[derive(Clone, Copy, Display, Eq, Hash, Ord, PartialEq, PartialOrd)]
18pub enum InternalError {
19    /// Size of input is empty or longer then [`u16::MAX`].
20    HashToScalar,
21    /// Computing HKDF failed while deriving subkeys
22    HkdfError,
23    /// Computing HMAC failed while supplying a secret key
24    HmacError,
25    /// Computing the key stretching function failed
26    KsfError,
27    /** This error occurs when the envelope seal open hmac check fails
28    HMAC check in seal open failed. */
29    SealOpenHmacError,
30    /** This error occurs when attempting to open an envelope of the wrong
31    type (base mode, custom identifier) */
32    IncompatibleEnvelopeModeError,
33    /// Error from the OPRF evaluation
34    OprfError(voprf::Error),
35    /// Error from the OPRF evaluation
36    OprfInternalError(voprf::InternalError),
37}
38
39impl Debug for InternalError {
40    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
41        match self {
42            Self::HashToScalar => f.debug_tuple("HashToScalar").finish(),
43            Self::HkdfError => f.debug_tuple("HkdfError").finish(),
44            Self::HmacError => f.debug_tuple("HmacError").finish(),
45            Self::KsfError => f.debug_tuple("KsfError").finish(),
46            Self::SealOpenHmacError => f.debug_tuple("SealOpenHmacError").finish(),
47            Self::IncompatibleEnvelopeModeError => {
48                f.debug_tuple("IncompatibleEnvelopeModeError").finish()
49            }
50            Self::OprfError(error) => f.debug_tuple("OprfError").field(error).finish(),
51            Self::OprfInternalError(error) => {
52                f.debug_tuple("OprfInternalError").field(error).finish()
53            }
54        }
55    }
56}
57
58impl Error for InternalError {}
59
60impl From<voprf::Error> for InternalError {
61    fn from(voprf_error: voprf::Error) -> Self {
62        Self::OprfError(voprf_error)
63    }
64}
65
66impl From<voprf::Error> for ProtocolError {
67    fn from(voprf_error: voprf::Error) -> Self {
68        Self::LibraryError(InternalError::OprfError(voprf_error))
69    }
70}
71
72impl From<voprf::InternalError> for ProtocolError {
73    fn from(voprf_error: voprf::InternalError) -> Self {
74        Self::LibraryError(InternalError::OprfInternalError(voprf_error))
75    }
76}
77
78/// Represents an error in protocol handling
79#[derive(Clone, Copy, Display, Eq, Hash, Ord, PartialEq, PartialOrd)]
80pub enum ProtocolError<T = Infallible> {
81    /// Internal error encountered
82    LibraryError(InternalError),
83    /// Error in validating credentials
84    InvalidLoginError,
85    /// Error with serializing / deserializing protocol messages
86    SerializationError,
87    /// Invalid length for `name`: expected `len`, but is actually `actual_len`.
88    SizeError {
89        /// name
90        name: &'static str,
91        /// length
92        len: usize,
93        /// actual
94        actual_len: usize,
95    },
96    /** This error occurs when the client detects that the server has
97    reflected the OPRF value (beta == alpha) */
98    ReflectedValueError,
99    /// Custom [`SecretKey`](crate::keypair::PrivateKeySerialization) error type
100    Custom(T),
101}
102
103impl<T: Debug> Debug for ProtocolError<T> {
104    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
105        match self {
106            Self::LibraryError(pake_error) => {
107                f.debug_tuple("LibraryError").field(pake_error).finish()
108            }
109            Self::InvalidLoginError => f.debug_tuple("InvalidLoginError").finish(),
110            Self::SerializationError => f.debug_tuple("SerializationError").finish(),
111            Self::SizeError {
112                name,
113                len,
114                actual_len,
115            } => f
116                .debug_struct("SizeError")
117                .field("name", name)
118                .field("len", len)
119                .field("actual_len", actual_len)
120                .finish(),
121            Self::ReflectedValueError => f.debug_tuple("ReflectedValueError").finish(),
122            Self::Custom(custom) => f.debug_tuple("Custom").field(custom).finish(),
123        }
124    }
125}
126
127impl<T: Error> Error for ProtocolError<T> {}
128
129// This is meant to express future(ly) non-trivial ways of converting the
130// internal error into a ProtocolError
131impl<T> From<InternalError> for ProtocolError<T> {
132    fn from(e: InternalError) -> ProtocolError<T> {
133        Self::LibraryError(e)
134    }
135}
136
137// See https://github.com/rust-lang/rust/issues/64715 and remove this when merged,
138// and https://github.com/dtolnay/thiserror/issues/62 for why this comes up in our
139// doc tests.
140impl<T> From<::core::convert::Infallible> for ProtocolError<T> {
141    fn from(_: ::core::convert::Infallible) -> Self {
142        unreachable!()
143    }
144}
145
146impl ProtocolError {
147    /// Convert `ProtocolError<Infallible>` into `ProtocolError<T>`
148    pub fn into_custom<T>(self) -> ProtocolError<T> {
149        match self {
150            Self::LibraryError(internal_error) => ProtocolError::LibraryError(internal_error),
151            Self::InvalidLoginError => ProtocolError::InvalidLoginError,
152            Self::SerializationError => ProtocolError::SerializationError,
153            Self::SizeError {
154                name,
155                len,
156                actual_len,
157            } => ProtocolError::SizeError {
158                name,
159                len,
160                actual_len,
161            },
162            Self::ReflectedValueError => ProtocolError::ReflectedValueError,
163        }
164    }
165}