From 914e21c0430c6ad61e4e9538ab50ddbb2f0f3167 Mon Sep 17 00:00:00 2001 From: asonix Date: Wed, 4 Oct 2023 12:11:29 -0500 Subject: [PATCH] Implement constant-time equality for delete tokens, inline alias cleanup --- Cargo.lock | 1 + Cargo.toml | 1 + src/lib.rs | 3 ++- src/queue.rs | 2 +- src/queue/cleanup.rs | 4 ++-- src/repo/delete_token.rs | 4 ++++ 6 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 296ae35..38b3860 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1860,6 +1860,7 @@ dependencies = [ "sled", "storage-path-generator", "streem", + "subtle", "thiserror", "time", "tokio", diff --git a/Cargo.toml b/Cargo.toml index f28a0e1..9b5eb85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ sha2 = "0.10.0" sled = { version = "0.34.7" } storage-path-generator = "0.1.0" streem = "0.2.0" +subtle = { version = "2.5.0", default-features = false } thiserror = "1.0" time = { version = "0.3.0", features = ["serde", "serde-well-known"] } tokio = { version = "1", features = ["full", "tracing"] } diff --git a/src/lib.rs b/src/lib.rs index 33881a5..19f874a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -712,7 +712,8 @@ async fn delete( let token = DeleteToken::from_existing(&token); let alias = Alias::from_existing(&alias); - queue::cleanup_alias(&repo, alias, token).await?; + // delete alias inline + queue::cleanup::alias(&repo, alias, token).await?; Ok(HttpResponse::NoContent().finish()) } diff --git a/src/queue.rs b/src/queue.rs index 94488ba..d7f4447 100644 --- a/src/queue.rs +++ b/src/queue.rs @@ -16,7 +16,7 @@ use std::{ }; use tracing::Instrument; -mod cleanup; +pub(crate) mod cleanup; mod process; const CLEANUP_QUEUE: &str = "cleanup"; diff --git a/src/queue/cleanup.rs b/src/queue/cleanup.rs index 2b91edb..41d4c5d 100644 --- a/src/queue/cleanup.rs +++ b/src/queue/cleanup.rs @@ -111,10 +111,10 @@ async fn hash(repo: &ArcRepo, hash: Hash) -> Result<(), Error> { } #[tracing::instrument(skip_all)] -async fn alias(repo: &ArcRepo, alias: Alias, token: DeleteToken) -> Result<(), Error> { +pub(crate) async fn alias(repo: &ArcRepo, alias: Alias, token: DeleteToken) -> Result<(), Error> { let saved_delete_token = repo.delete_token(&alias).await?; - if saved_delete_token.is_some() && saved_delete_token != Some(token) { + if !saved_delete_token.is_some_and(|t| t.ct_eq(&token)) { return Err(UploadError::InvalidToken.into()); } diff --git a/src/repo/delete_token.rs b/src/repo/delete_token.rs index ca1a50f..a7ae07b 100644 --- a/src/repo/delete_token.rs +++ b/src/repo/delete_token.rs @@ -71,6 +71,10 @@ impl DeleteToken { None } } + + pub(crate) fn ct_eq(&self, rhs: &Self) -> bool { + subtle::ConstantTimeEq::ct_eq(self.id.as_bytes(), rhs.id.as_bytes()).unwrap_u8() == 1 + } } impl std::str::FromStr for DeleteToken {