1#[cfg(feature = "derive")]
2use crate::Errorizable;
3
4pub type Result<T> = core::result::Result<T, HandshakeError>;
5
6#[cfg_attr(feature = "derive", derive(Errorizable))]
8#[derive(Debug)]
9pub enum HandshakeError {
10 #[cfg_attr(
13 feature = "derive",
14 error("Handshake invariant violation: transcript already locked")
15 )]
16 TranscriptAlreadyLocked,
17 #[cfg_attr(
18 feature = "derive",
19 error("Handshake invariant violation: transcript not locked")
20 )]
21 TranscriptNotLocked,
22 #[cfg_attr(
23 feature = "derive",
24 error("Handshake invariant violation: AEAD key already derived")
25 )]
26 AeadAlreadyDerived,
27 #[cfg_attr(
28 feature = "derive",
29 error("Handshake invariant violation: Finished already sent")
30 )]
31 FinishedAlreadySent,
32 #[cfg_attr(
33 feature = "derive",
34 error("Handshake invariant violation: Finished before transcript lock")
35 )]
36 FinishedBeforeTranscriptLock,
37 #[cfg_attr(feature = "derive", error("Invalid client key exchange message"))]
39 InvalidClientKeyExchange,
40
41 #[cfg_attr(feature = "derive", error("Invalid server key exchange message"))]
43 InvalidServerKeyExchange,
44
45 #[cfg_attr(feature = "derive", error("Invalid public key in handshake: {0}"))]
47 #[cfg_attr(feature = "derive", from)]
48 InvalidPublicKey(crate::crypto::sign::ecdsa::k256::elliptic_curve::Error),
49
50 #[cfg_attr(feature = "derive", error("Invalid certificate: {0}"))]
52 #[cfg_attr(feature = "derive", from)]
53 CertificateValidationError(crate::crypto::x509::error::CertificateValidationError),
54
55 #[cfg_attr(feature = "derive", error("Handshake signature verification failed"))]
57 SignatureVerificationFailed,
58
59 #[cfg_attr(feature = "derive", error("Signature error: {0}"))]
61 #[cfg_attr(feature = "derive", from)]
62 SignatureError(crate::crypto::sign::Error),
63
64 #[cfg_attr(feature = "derive", error("Handshake key derivation failed: {0}"))]
66 #[cfg_attr(feature = "derive", from)]
67 KeyDerivationFailed(crate::crypto::aead::Error),
68
69 #[cfg_attr(feature = "derive", error("DER error: {0}"))]
71 #[cfg_attr(feature = "derive", from)]
72 DerError(crate::der::Error),
73
74 #[cfg_attr(feature = "derive", error("SPKI error: {0}"))]
76 #[cfg_attr(feature = "derive", from)]
77 SpkiError(crate::spki::Error),
78
79 #[cfg_attr(feature = "derive", error("Key provider error: {0}"))]
81 #[cfg_attr(feature = "derive", from)]
82 KeyError(crate::crypto::key::KeyError),
83
84 #[cfg_attr(feature = "derive", error("CMS builder error: {0}"))]
86 #[cfg_attr(feature = "derive", from)]
87 CmsBuilderError(crate::cms::builder::Error),
88
89 #[cfg_attr(feature = "derive", error("Invalid handshake state"))]
91 InvalidState,
92
93 #[cfg_attr(feature = "derive", error("Missing server key"))]
95 MissingServerKey,
96
97 #[cfg_attr(feature = "derive", error("Missing server certificate"))]
99 MissingServerCertificate,
100
101 #[cfg_attr(feature = "derive", error("Missing client certificate"))]
103 MissingClientCertificate,
104
105 #[cfg_attr(feature = "derive", error("Invalid transcript hash"))]
107 InvalidTranscriptHash,
108
109 #[cfg_attr(
111 feature = "derive",
112 error("Server requires mutual authentication but client has no identity")
113 )]
114 MutualAuthRequired,
115
116 #[cfg_attr(
118 feature = "derive",
119 error("Peer identity changed during re-handshake - connection identity is immutable")
120 )]
121 PeerIdentityMismatch,
122
123 #[cfg_attr(feature = "derive", error("Missing client random from ClientHello"))]
125 MissingClientRandom,
126
127 #[cfg_attr(feature = "derive", error("Missing base session key"))]
129 MissingBaseSessionKey,
130
131 #[cfg_attr(feature = "derive", error("Missing client random"))]
133 MissingClientRandomState,
134
135 #[cfg_attr(feature = "derive", error("Missing server random"))]
137 MissingServerRandom,
138
139 #[cfg_attr(
141 feature = "derive",
142 error("CMS salt too short: {actual} bytes (minimum {minimum} required)")
143 )]
144 InsufficientSaltEntropy { actual: usize, minimum: usize },
145
146 #[cfg_attr(feature = "derive", error("Handshake aborted by peer: {0:?}"))]
148 AbortReceived(crate::transport::handshake::HandshakeAlert),
149
150 #[cfg_attr(feature = "derive", error("Handshake timeout"))]
152 Timeout,
153
154 #[cfg_attr(feature = "derive", error("Server selected profile not in client's offer"))]
156 InvalidProfileSelection,
157
158 #[cfg_attr(feature = "derive", error("Profile negotiation failed: {0}"))]
160 #[cfg_attr(feature = "derive", from)]
161 NegotiationError(crate::transport::handshake::negotiation::NegotiationError),
162
163 #[cfg_attr(feature = "derive", error("No mutually supported cryptographic profiles found"))]
165 NoMutualProfiles,
166
167 #[cfg_attr(
169 feature = "derive",
170 error("Dealer's choice failed: no supported profiles configured")
171 )]
172 NoSupportedProfiles,
173
174 #[cfg_attr(
176 feature = "derive",
177 error("Profile negotiation required but no profiles configured on server")
178 )]
179 NegotiationRequired,
180
181 #[cfg_attr(feature = "derive", error("Certificate rejected by policy: {0}"))]
183 #[cfg_attr(feature = "derive", from)]
184 CertificatePolicyError(crate::crypto::policy::CryptoPolicyError),
185
186 #[cfg_attr(feature = "derive", error("Attribute must contain exactly one value"))]
188 InvalidAttributeArity,
189 #[cfg_attr(feature = "derive", error("Duplicate attribute present"))]
190 DuplicateAttribute,
191 #[cfg_attr(feature = "derive", error("Required attribute missing"))]
192 MissingAttribute,
193 #[cfg_attr(feature = "derive", error("Nonce value not valid OCTET STRING"))]
194 InvalidNonceEncoding,
195 #[cfg_attr(feature = "derive", error("Nonce length mismatch: {0}"))]
196 NonceLengthError(crate::error::ReceivedExpectedError<usize, usize>),
197 #[cfg_attr(feature = "derive", error("OCTET STRING length mismatch: {0}"))]
198 OctetStringLengthError(crate::error::ReceivedExpectedError<usize, usize>),
199 #[cfg_attr(feature = "derive", error("Version/alert value not valid INTEGER"))]
200 InvalidIntegerEncoding,
201 #[cfg_attr(feature = "derive", error("INTEGER out of range"))]
202 IntegerOutOfRange,
203 #[cfg_attr(feature = "derive", error("Unknown alert code: {0:?}"))]
204 UnknownAlertCode(u8),
205
206 #[cfg_attr(feature = "derive", error("Certificate not yet valid"))]
208 CertificateNotYetValid,
209 #[cfg_attr(feature = "derive", error("Certificate expired"))]
210 CertificateExpired,
211 #[cfg_attr(feature = "derive", error("Invalid timestamp"))]
212 InvalidTimestamp,
213
214 #[cfg(feature = "ecies")]
216 #[cfg_attr(feature = "derive", error("ECIES operation failed: {0}"))]
217 #[cfg_attr(feature = "derive", from)]
218 EciesError(crate::crypto::ecies::EciesError),
219 #[cfg_attr(feature = "derive", error("Missing encrypted content in ECIES message"))]
220 MissingEncryptedContent,
221 #[cfg_attr(feature = "derive", error("Invalid decrypted payload size"))]
222 InvalidDecryptedPayloadSize,
223 #[cfg_attr(feature = "derive", error("client_random mismatch - possible replay attack"))]
224 ClientRandomMismatchReplay,
225
226 #[cfg_attr(feature = "derive", error("ECDH operation failed"))]
228 EcdhFailed,
229 #[cfg_attr(feature = "derive", error("KDF operation failed"))]
230 KdfError,
231 #[cfg_attr(
232 feature = "derive",
233 error("Invalid key size: expected {expected}, got {received}")
234 )]
235 InvalidKeySize { expected: usize, received: usize },
236 #[cfg_attr(feature = "derive", error("ASN.1 encoding error: {0}"))]
237 Asn1Error(der::Error),
238 #[cfg_attr(feature = "derive", error("Invalid recipient index"))]
239 InvalidRecipientIndex,
240 #[cfg_attr(feature = "derive", error("Missing UKM in KeyAgreeRecipientInfo"))]
241 MissingUkm,
242 #[cfg_attr(feature = "derive", error("Failed to parse originator public key"))]
243 InvalidOriginatorPublicKey,
244 #[cfg_attr(feature = "derive", error("Unsupported originator identifier type"))]
245 UnsupportedOriginatorIdentifier,
246 #[cfg_attr(feature = "derive", error("KARI builder already consumed"))]
247 KariBuilderConsumed,
248 #[cfg_attr(feature = "derive", error("Content encryption algorithm not set"))]
249 MissingContentEncryptionAlgorithm,
250 #[cfg_attr(
251 feature = "derive",
252 error("Key wrap algorithm not configured in security profile")
253 )]
254 MissingKeyWrapAlgorithm,
255 #[cfg(all(feature = "builder", feature = "aead"))]
256 #[cfg_attr(feature = "derive", error("AES key wrap operation failed: {0}"))]
257 #[cfg_attr(feature = "derive", from)]
258 AesKeyWrap(crate::crypto::aead::aes_kw::Error),
259
260 #[cfg(feature = "kem")]
261 #[cfg_attr(
262 feature = "derive",
263 error("Hybrid key agreement integrity check failed: combined ECDH+KEM key validation error")
264 )]
265 HybridKariIntegrityCheckFailed,
266
267 #[cfg_attr(feature = "derive", error("Random generation failed"))]
269 RandomGenerationFailed,
270
271 #[cfg_attr(feature = "derive", error("Invalid OCTET STRING length: {0}"))]
273 InvalidOctetStringLength(&'static str),
274}
275
276#[cfg(not(feature = "derive"))]
277impl core::fmt::Display for HandshakeError {
278 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
279 match self {
280 HandshakeError::InvalidClientKeyExchange => write!(f, "Invalid client key exchange message"),
281 HandshakeError::InvalidServerKeyExchange => write!(f, "Invalid server key exchange message"),
282 HandshakeError::InvalidPublicKey(e) => write!(f, "Invalid public key in handshake: {}", e),
283 HandshakeError::CertificateValidationError(e) => write!(f, "Invalid certificate: {}", e),
284 HandshakeError::SpkiError(e) => write!(f, "SPKI error: {}", e),
285 HandshakeError::KeyError(e) => write!(f, "Key provider error: {}", e),
286 HandshakeError::CmsBuilderError(e) => write!(f, "CMS builder error: {}", e),
287 HandshakeError::SignatureVerificationFailed => write!(f, "Handshake signature verification failed"),
288 HandshakeError::KeyDerivationFailed(e) => write!(f, "Handshake key derivation failed: {}", e),
289 HandshakeError::InvalidState => write!(f, "Invalid handshake state"),
290 HandshakeError::MissingServerKey => write!(f, "Missing server key"),
291 HandshakeError::MissingServerCertificate => write!(f, "Missing server certificate"),
292 HandshakeError::MissingClientCertificate => write!(f, "Missing client certificate"),
293 HandshakeError::InvalidTranscriptHash => write!(f, "Invalid transcript hash"),
294 HandshakeError::MissingClientRandom => write!(f, "Missing client random from ClientHello"),
295 HandshakeError::MissingBaseSessionKey => write!(f, "Missing base session key"),
296 HandshakeError::MissingClientRandomState => write!(f, "Missing client random"),
297 HandshakeError::MissingServerRandom => write!(f, "Missing server random"),
298 HandshakeError::InsufficientSaltEntropy { actual, minimum } => {
299 write!(f, "CMS salt too short: {} bytes (minimum {} required)", actual, minimum)
300 }
301 HandshakeError::AbortReceived(alert) => write!(f, "Handshake aborted by peer: {:?}", alert),
302 HandshakeError::Timeout => write!(f, "Handshake timeout"),
303 HandshakeError::InvalidProfileSelection => write!(f, "Server selected profile not in client's offer"),
304 HandshakeError::NegotiationError(e) => write!(f, "Profile negotiation failed: {}", e),
305 HandshakeError::NoMutualProfiles => write!(f, "No mutually supported cryptographic profiles found"),
306 HandshakeError::NoSupportedProfiles => {
307 write!(f, "Dealer's choice failed: no supported profiles configured")
308 }
309 HandshakeError::NegotiationRequired => {
310 write!(f, "Profile negotiation required but no profiles configured on server")
311 }
312 HandshakeError::CertificatePolicyError(e) => write!(f, "Certificate rejected by policy: {}", e),
313 HandshakeError::DerError(e) => write!(f, "DER error: {}", e),
314 HandshakeError::InvalidAttributeArity => write!(f, "Attribute must contain exactly one value"),
315 HandshakeError::DuplicateAttribute => write!(f, "Duplicate attribute present"),
316 HandshakeError::MissingAttribute => write!(f, "Required attribute missing"),
317 HandshakeError::InvalidNonceEncoding => write!(f, "Nonce value not valid OCTET STRING"),
318 HandshakeError::NonceLengthError(e) => write!(f, "Nonce length mismatch: {}", e),
319 HandshakeError::OctetStringLengthError(e) => write!(f, "OCTET STRING length mismatch: {}", e),
320 HandshakeError::InvalidIntegerEncoding => write!(f, "Version/alert value not valid INTEGER"),
321 HandshakeError::IntegerOutOfRange => write!(f, "INTEGER out of range"),
322 HandshakeError::UnknownAlertCode(code) => write!(f, "Unknown alert code: {code}"),
323 HandshakeError::CertificateNotYetValid => write!(f, "Certificate not yet valid"),
324 HandshakeError::CertificateExpired => write!(f, "Certificate expired"),
325 HandshakeError::InvalidTimestamp => write!(f, "Invalid timestamp"),
326 HandshakeError::EciesError(e) => write!(f, "ECIES operation failed: {}", e),
327 HandshakeError::MissingEncryptedContent => write!(f, "Missing encrypted content in ECIES message"),
328 HandshakeError::InvalidDecryptedPayloadSize => write!(f, "Invalid decrypted payload size"),
329 HandshakeError::ClientRandomMismatchReplay => write!(f, "client_random mismatch - possible replay attack"),
330 HandshakeError::EcdhFailed => write!(f, "ECDH operation failed"),
331 HandshakeError::KdfError => write!(f, "KDF operation failed"),
332 HandshakeError::InvalidKeySize { expected, received } => {
333 write!(f, "Invalid key size: expected {}, got {}", expected, received)
334 }
335 HandshakeError::Asn1Error(e) => write!(f, "ASN.1 encoding error: {}", e),
336 HandshakeError::InvalidRecipientIndex => write!(f, "Invalid recipient index"),
337 HandshakeError::MissingUkm => write!(f, "Missing UKM in KeyAgreeRecipientInfo"),
338 HandshakeError::InvalidOriginatorPublicKey => write!(f, "Failed to parse originator public key"),
339 HandshakeError::UnsupportedOriginatorIdentifier => write!(f, "Unsupported originator identifier type"),
340 HandshakeError::KariBuilderConsumed => write!(f, "KARI builder already consumed"),
341 HandshakeError::MissingContentEncryptionAlgorithm => write!(f, "Content encryption algorithm not set"),
342 HandshakeError::MissingKeyWrapAlgorithm => {
343 write!(f, "Key wrap algorithm not configured in security profile")
344 }
345 #[cfg(all(feature = "builder", feature = "aead"))]
346 HandshakeError::AesKeyWrap(e) => write!(f, "AES key wrap operation failed: {}", e),
347 HandshakeError::RandomGenerationFailed => write!(f, "Random generation failed"),
348 HandshakeError::InvalidOctetStringLength(m) => write!(f, "Invalid OCTET STRING length: {}", m),
349 HandshakeError::NonceLengthError(e) => write!(f, "Nonce length mismatch: {}", e),
350 HandshakeError::OctetStringLengthError(e) => write!(f, "OCTET STRING length mismatch: {}", e),
351 HandshakeError::UnknownAlertCode(code) => write!(f, "Unknown alert code: {code}"),
352 }
353 }
354}
355
356#[cfg(not(feature = "derive"))]
357impl core::error::Error for HandshakeError {}
358
359impl From<crate::crypto::kdf::KdfError> for HandshakeError {
360 fn from(_: crate::crypto::kdf::KdfError) -> Self {
361 HandshakeError::KeyDerivationFailed(crate::crypto::aead::Error)
362 }
363}
364
365impl From<crypto_common::InvalidLength> for HandshakeError {
366 fn from(_: crypto_common::InvalidLength) -> Self {
367 HandshakeError::KeyDerivationFailed(crate::crypto::aead::Error)
368 }
369}
370
371#[cfg(not(feature = "derive"))]
372impl From<crate::crypto::key::KeyError> for HandshakeError {
373 fn from(e: crate::crypto::key::KeyError) -> Self {
374 HandshakeError::KeyError(e)
375 }
376}