diff --git a/server/Cargo.lock b/server/Cargo.lock index e2c621d..836a999 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -707,6 +707,7 @@ dependencies = [ "memsafe", "ml-dsa", "rand 0.10.1", + "thiserror 2.0.18", "x-wing", ] diff --git a/server/crates/arbiter-crypto/Cargo.toml b/server/crates/arbiter-crypto/Cargo.toml index 5d85e6e..b544b33 100644 --- a/server/crates/arbiter-crypto/Cargo.toml +++ b/server/crates/arbiter-crypto/Cargo.toml @@ -11,6 +11,7 @@ hmac.workspace = true alloy.workspace = true x-wing = { version = "0.1.0-rc.0", features = ["zeroize"] } chrono.workspace = true +thiserror.workspace = true [lints] workspace = true diff --git a/server/crates/arbiter-crypto/src/authn/v1.rs b/server/crates/arbiter-crypto/src/authn/v1.rs index fbcd8a3..94aa9d2 100644 --- a/server/crates/arbiter-crypto/src/authn/v1.rs +++ b/server/crates/arbiter-crypto/src/authn/v1.rs @@ -11,6 +11,13 @@ pub static USERAGENT_CONTEXT: &[u8] = b"arbiter_user_agent"; const NONCE_SIZE: usize = 32; +#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)] +#[error("invalid length: expected {expected} bytes, got {actual} bytes")] +pub struct InvalidLength { + pub expected: usize, + pub actual: usize, +} + #[derive(Debug, Clone)] pub struct AuthChallenge { pub nonce: [u8; NONCE_SIZE], @@ -43,8 +50,11 @@ impl AuthChallenge { } } - pub fn from_parts(nonce: &[u8], timestamp: i64) -> Result { - let random_nonce = nonce.as_array().ok_or(())?; + pub fn from_parts(nonce: &[u8], timestamp: i64) -> Result { + let random_nonce = nonce.as_array().ok_or(InvalidLength { + expected: NONCE_SIZE, + actual: nonce.len(), + })?; Ok(AuthChallenge { nonce: *random_nonce, timestamp: DateTime::from_timestamp_nanos(timestamp), diff --git a/server/crates/arbiter-server/src/grpc/user_agent/vault_gate.rs b/server/crates/arbiter-server/src/grpc/user_agent/vault_gate.rs index 557f77d..bffa5cc 100644 --- a/server/crates/arbiter-server/src/grpc/user_agent/vault_gate.rs +++ b/server/crates/arbiter-server/src/grpc/user_agent/vault_gate.rs @@ -15,37 +15,35 @@ mod outbound; #[async_trait] impl Receiver for AuthTransportAdapter<'_> { async fn recv(&mut self) -> Option { - loop { - let request = match self.bi_mut().recv().await? { - Ok(request) => request, - Err(error) => { - warn!( - ?error, - "Failed to receive user agent request during vault gate" - ); - return None; - } - }; - - if let Err(err) = self.tracker_mut().request(request.id) { - let _ = self.bi_mut().send(Err(err)).await; + let request = match self.bi_mut().recv().await? { + Ok(request) => request, + Err(error) => { + warn!( + ?error, + "Failed to receive user agent request during vault gate" + ); return None; } + }; - let Some(payload) = request.payload else { - let _ = self - .bi_mut() - .send(Err(Status::invalid_argument("Missing request payload"))) - .await; - return None; - }; + if let Err(err) = self.tracker_mut().request(request.id) { + let _ = self.bi_mut().send(Err(err)).await; + return None; + } - match payload.try_convert() { - Ok(inbound) => return Some(inbound), - Err(status) => { - let _ = self.bi_mut().send(Err(status)).await; - return None; - } + let Some(payload) = request.payload else { + let _ = self + .bi_mut() + .send(Err(Status::invalid_argument("Missing request payload"))) + .await; + return None; + }; + + match payload.try_convert() { + Ok(inbound) => Some(inbound), + Err(status) => { + let _ = self.bi_mut().send(Err(status)).await; + None } } } diff --git a/server/crates/arbiter-server/src/peers/user_agent/mod.rs b/server/crates/arbiter-server/src/peers/user_agent/mod.rs index d1806ce..055b53f 100644 --- a/server/crates/arbiter-server/src/peers/user_agent/mod.rs +++ b/server/crates/arbiter-server/src/peers/user_agent/mod.rs @@ -81,7 +81,7 @@ async fn verify_integrity( .get() .await .map_err(|_| Error::Internal("DB unavailable".into()))?; - match integrity::verify_entity(&mut conn, &vault, credentials, credentials.id).await { + match integrity::verify_entity(&mut conn, vault, credentials, credentials.id).await { Ok(AttestationStatus::Attested) => Ok(()), Ok(AttestationStatus::Unavailable) => { Err(Error::Internal("Vault sealed during promotion".into())) diff --git a/server/crates/arbiter-server/src/peers/user_agent/vault_gate/mod.rs b/server/crates/arbiter-server/src/peers/user_agent/vault_gate/mod.rs index fe74c8c..1c0f4b9 100644 --- a/server/crates/arbiter-server/src/peers/user_agent/vault_gate/mod.rs +++ b/server/crates/arbiter-server/src/peers/user_agent/vault_gate/mod.rs @@ -132,7 +132,7 @@ impl VaultGate { let secret = ephemeral_secret.diffie_hellman(&client_pubkey); self.state = State::ReadyForExchange { - server_key: public_key.clone(), + server_key: public_key, secret, }; @@ -179,7 +179,7 @@ impl VaultGate { } Err(err) => { error!(?err, "Failed to send unseal request to vault"); - Err(Error::internal("Vault actor error").into()) + Err(Error::internal("Vault actor error")) } } }