use borsh::{BorshDeserialize, BorshSerialize};
use qos_p256::P256Error;
use crate::{
client::ClientError,
io::IOError,
protocol::{ProtocolPhase, services::boot},
};
#[derive(
Debug,
Clone,
PartialEq,
Eq,
BorshSerialize,
BorshDeserialize,
serde::Serialize,
serde::Deserialize,
)]
pub enum ProtocolError {
InvalidShare,
ReconstructionErrorEmptySecret,
ReconstructionErrorIncorrectPubKey,
IOError,
InvalidManifestApproval(boot::Approval),
NotEnoughApprovals,
NoMatchingRoute(ProtocolPhase),
InvalidPivotHash {
expected: String,
actual: String,
},
InvalidPivotEnv(String),
OversizeMsg,
InvalidMsg,
EnclaveClient,
DecryptionFailed,
InvalidPrivateKey,
FailedToParseFromString,
BadEphemeralKeyPath,
CannotModifyPostPivotStatic,
FailedToGetEphemeralKey(P256Error),
FailedToPutEphemeralKey,
CannotRotateNonExistentEphemeralKey,
CannotDeleteEphemeralKey(String),
FailedToGetQuorumKey(P256Error),
FailedToPutQuorumKey,
FailedToGetManifestEnvelope,
FailedToPutManifestEnvelope,
FailedToPutPivot,
AppClientRecvTimeout,
AppClientRecvInterrupted,
AppClientRecvConnectionClosed,
AppClientConnectError(String),
AppClientSendError(String),
AppClientError(String),
OversizedPayload,
ProtocolMsgDeserialization,
BadShareSetApprovals,
CouldNotVerifyApproval,
NotShareSetMember,
NotManifestSetMember,
P256Error(qos_p256::P256Error),
InvalidP256DRKey(qos_p256::P256Error),
IncorrectSecretLen,
QosAttestError(String),
DifferentQuorumKey {
expected: String,
actual: String,
},
DifferentManifestSet {
expected: String,
actual: String,
},
DifferentNamespaceName {
expected: String,
actual: String,
},
LowNonce {
#[serde(with = "qos_json::string_or_numeric")]
expected: u32,
#[serde(with = "qos_json::string_or_numeric")]
actual: u32,
},
DifferentPcr3 {
expected: String,
actual: String,
},
MissingEphemeralKey,
InvalidEphemeralKey,
InvalidEncryptedQuorumKeySignature,
EncryptedQuorumKeyInvalidLen,
InvalidQuorumSecret,
WrongQuorumKey,
InvalidStateTransition(ProtocolPhase, ProtocolPhase),
DuplicateApproval,
DifferentManifest {
expected: String,
actual: String,
},
QosCrypto(String),
PoolExpandError,
}
impl From<std::io::Error> for ProtocolError {
fn from(_err: std::io::Error) -> Self {
Self::IOError
}
}
impl From<ClientError> for ProtocolError {
fn from(err: ClientError) -> Self {
match err {
ClientError::IOError(IOError::RecvTimeout) => {
ProtocolError::AppClientRecvTimeout
}
ClientError::IOError(IOError::RecvInterrupted) => {
ProtocolError::AppClientRecvInterrupted
}
ClientError::IOError(IOError::RecvConnectionClosed) => {
ProtocolError::AppClientRecvConnectionClosed
}
ClientError::IOError(IOError::ConnectNixError(e)) => {
ProtocolError::AppClientConnectError(format!("{e:?}"))
}
ClientError::IOError(IOError::SendNixError(e)) => {
ProtocolError::AppClientSendError(format!("{e:?}"))
}
e => ProtocolError::AppClientError(format!("{e:?}")),
}
}
}
impl From<qos_p256::P256Error> for ProtocolError {
fn from(err: qos_p256::P256Error) -> Self {
Self::P256Error(err)
}
}
impl From<qos_nsm::nitro::AttestError> for ProtocolError {
fn from(err: qos_nsm::nitro::AttestError) -> Self {
let msg = format!("{err:?}");
Self::QosAttestError(msg)
}
}
impl std::fmt::Display for ProtocolError {
#[allow(clippy::too_many_lines)]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::InvalidShare => write!(f, "invalid quorum key share"),
Self::ReconstructionErrorEmptySecret => {
write!(f, "failed to reconstruct quorum key: empty secret")
}
Self::ReconstructionErrorIncorrectPubKey => {
write!(f, "reconstructed incorrect public key")
}
Self::IOError => write!(f, "filesystem error"),
Self::InvalidManifestApproval(approval) => {
write!(
f,
"invalid manifest approval from member '{}'",
approval.member.alias
)
}
Self::NotEnoughApprovals => write!(f, "not enough approvals"),
Self::NoMatchingRoute(phase) => {
write!(f, "no matching route for phase {phase:?}")
}
Self::InvalidPivotHash { expected, actual } => {
write!(
f,
"invalid pivot hash: expected {expected}, got {actual}"
)
}
Self::InvalidPivotEnv(e) => write!(f, "invalid pivot env: {e}"),
Self::OversizeMsg => write!(f, "message too large"),
Self::InvalidMsg => write!(f, "invalid message"),
Self::EnclaveClient => write!(f, "enclave client error"),
Self::DecryptionFailed => write!(f, "decryption failed"),
Self::InvalidPrivateKey => write!(f, "invalid private key"),
Self::FailedToParseFromString => {
write!(f, "failed to parse from string")
}
Self::BadEphemeralKeyPath => write!(f, "bad ephemeral key path"),
Self::CannotModifyPostPivotStatic => {
write!(f, "cannot modify state after pivot")
}
Self::FailedToGetEphemeralKey(e) => {
write!(f, "failed to get ephemeral key: {e:?}")
}
Self::FailedToPutEphemeralKey => {
write!(f, "failed to put ephemeral key")
}
Self::CannotRotateNonExistentEphemeralKey => {
write!(f, "cannot rotate non-existent ephemeral key")
}
Self::CannotDeleteEphemeralKey(e) => {
write!(f, "cannot delete ephemeral key: {e}")
}
Self::FailedToGetQuorumKey(e) => {
write!(f, "failed to get quorum key: {e:?}")
}
Self::FailedToPutQuorumKey => write!(f, "failed to put quorum key"),
Self::FailedToGetManifestEnvelope => {
write!(f, "failed to get manifest envelope")
}
Self::FailedToPutManifestEnvelope => {
write!(f, "failed to put manifest envelope")
}
Self::FailedToPutPivot => write!(f, "failed to put pivot"),
Self::AppClientRecvTimeout => {
write!(f, "app client receive timeout")
}
Self::AppClientRecvInterrupted => {
write!(f, "app client receive interrupted")
}
Self::AppClientRecvConnectionClosed => {
write!(f, "app client connection closed")
}
Self::AppClientConnectError(e) => {
write!(f, "app client connect error: {e}")
}
Self::AppClientSendError(e) => {
write!(f, "app client send error: {e}")
}
Self::AppClientError(e) => write!(f, "app client error: {e}"),
Self::OversizedPayload => write!(f, "oversized payload"),
Self::ProtocolMsgDeserialization => {
write!(f, "protocol message deserialization failed")
}
Self::BadShareSetApprovals => {
write!(f, "unexpected share set approvals")
}
Self::CouldNotVerifyApproval => {
write!(f, "could not verify approval")
}
Self::NotShareSetMember => write!(f, "not a share set member"),
Self::NotManifestSetMember => {
write!(f, "not a manifest set member")
}
Self::P256Error(e) => write!(f, "P256 error: {e:?}"),
Self::InvalidP256DRKey(e) => {
write!(f, "invalid P256 DR key: {e:?}")
}
Self::IncorrectSecretLen => write!(f, "incorrect secret length"),
Self::QosAttestError(e) => write!(f, "attestation error: {e}"),
Self::DifferentQuorumKey { expected, actual } => {
write!(
f,
"different quorum key: expected {expected}, got {actual}"
)
}
Self::DifferentManifestSet { expected, actual } => {
write!(
f,
"different manifest set: expected {expected}, got {actual}"
)
}
Self::DifferentNamespaceName { expected, actual } => {
write!(
f,
"different namespace name: expected '{expected}', got '{actual}'"
)
}
Self::LowNonce { expected, actual } => {
write!(
f,
"manifest nonce too low: expected >= {expected}, got {actual}"
)
}
Self::DifferentPcr3 { expected, actual } => {
write!(f, "different PCR3: expected {expected}, got {actual}")
}
Self::MissingEphemeralKey => write!(f, "missing ephemeral key"),
Self::InvalidEphemeralKey => write!(f, "invalid ephemeral key"),
Self::InvalidEncryptedQuorumKeySignature => {
write!(f, "invalid encrypted quorum key signature")
}
Self::EncryptedQuorumKeyInvalidLen => {
write!(f, "encrypted quorum key has invalid length")
}
Self::InvalidQuorumSecret => write!(f, "invalid quorum secret"),
Self::WrongQuorumKey => write!(f, "wrong quorum key"),
Self::InvalidStateTransition(from, to) => {
write!(f, "invalid state transition from {from:?} to {to:?}")
}
Self::DuplicateApproval => write!(f, "duplicate approval"),
Self::DifferentManifest { expected, actual } => {
write!(
f,
"different manifest: expected {expected}, got {actual}"
)
}
Self::QosCrypto(e) => write!(f, "crypto error: {e}"),
Self::PoolExpandError => write!(f, "pool expand error"),
}
}
}
impl std::error::Error for ProtocolError {}