From abd9dc041188983e4dc1cd4890055dda80df94c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Mart=C3=ADn?= Date: Thu, 4 Apr 2024 13:27:21 +0200 Subject: [PATCH] feat(owner-onboarding-server): verify the device certificate chain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make `trusted_device_keys_path` configuration variable optional and if specified, check the device certificate chain with the provided trusted CA certs. If the configuration variable is not provided the server will still check the device certificate chain is well formed. Signed-off-by: Miguel Martín --- HOWTO.md | 4 +- admin-tool/src/aio/configure.rs | 8 +-- owner-onboarding-server/src/main.rs | 50 ++++++++++++++----- .../configuration/owner_onboarding_server.rs | 2 +- 4 files changed, 45 insertions(+), 19 deletions(-) diff --git a/HOWTO.md b/HOWTO.md index 6eef24888..c6a6af0b5 100644 --- a/HOWTO.md +++ b/HOWTO.md @@ -491,8 +491,8 @@ Where: Please refer to the [Database management section](#database-management) on how to initialize databases. - `session_store_driver`: path to a directory that will hold session information. -- `trusted_device_keys_path`: path to the Device Certificate Authority - certificate. +- `trusted_device_keys_path` [OPTIONAL]: path to the CA certificates +used for device certificate chain verification. - `owner_private_key_path`: path to the Owner's private key. - `owner_public_key_path`: path to the Owner's public key certificate. - `bind`: IP address and port that this server will take. diff --git a/admin-tool/src/aio/configure.rs b/admin-tool/src/aio/configure.rs index 89d256797..abf39e710 100644 --- a/admin-tool/src/aio/configure.rs +++ b/admin-tool/src/aio/configure.rs @@ -330,10 +330,10 @@ fn generate_configs(aio_dir: &Path, config_args: &Configuration) -> Result<(), E ownership_voucher_store_driver: StoreConfig::Directory { path: aio_dir.join("stores").join("owner_vouchers"), }, - trusted_device_keys_path: AbsolutePathBuf::new( - aio_dir.join("keys").join("device_ca_cert.pem"), - ) - .unwrap(), + trusted_device_keys_path: Some( + AbsolutePathBuf::new(aio_dir.join("keys").join("device_ca_cert.pem")) + .expect("Failed to build absolute path"), + ), owner_private_key_path: AbsolutePathBuf::new( aio_dir.join("keys").join("owner_key.der"), ) diff --git a/owner-onboarding-server/src/main.rs b/owner-onboarding-server/src/main.rs index 307c8f609..6f7ab2af7 100644 --- a/owner-onboarding-server/src/main.rs +++ b/owner-onboarding-server/src/main.rs @@ -42,8 +42,7 @@ mod handlers; pub(crate) struct OwnerServiceUD { // Trusted keys - #[allow(dead_code)] - trusted_device_keys: X5Bag, + trusted_device_keys: Option, // Stores ownership_voucher_store: Box< @@ -90,6 +89,7 @@ async fn _handle_report_to_rendezvous(udt: &OwnerServiceUDT, ov: &OwnershipVouch &udt.owner_addresses, &udt.owner_key, udt.ov_registration_period, + &udt.trusted_device_keys, ) .await { @@ -172,6 +172,7 @@ async fn check_registration_window(udt: &OwnerServiceUDT) -> Result<()> { &udt.owner_addresses, &udt.owner_key, udt.ov_registration_period, + &udt.trusted_device_keys, ) .await { @@ -210,6 +211,7 @@ async fn report_ov_to_rendezvous( owner_addresses: &[TO2AddressEntry], owner_key: &PKey, registration_period: u32, + trusted_device_keys: &Option, ) -> Result { let ov_header = ov.header(); if ov_header.protocol_version() != ProtocolVersion::Version1_1 { @@ -219,6 +221,24 @@ async fn report_ov_to_rendezvous( ProtocolVersion::Version1_1 ); } + + match ov.device_certificate_chain() { + None => { + bail!("No device certificate chain found"); + } + Some(device_cert_chain) => { + if let Some(trusted_device_keys) = trusted_device_keys { + device_cert_chain + .verify_from_x5bag(trusted_device_keys) + .context("Device certificate is not trusted")? + } else { + device_cert_chain + .insecure_verify_without_root_verification() + .context("Device certificate chain is malformed")? + }; + } + }; + // Determine the RV IP let rv_info = ov_header .rendezvous_info() @@ -380,16 +400,22 @@ async fn main() -> Result<()> { // Bind information let bind_addr = settings.bind.clone(); - // Trusted keys - let trusted_device_keys = { - let trusted_keys_path = &settings.trusted_device_keys_path; - let contents = std::fs::read(trusted_keys_path).with_context(|| { - format!("Error reading trusted device keys from {trusted_keys_path}") - })?; - X509::stack_from_pem(&contents).context("Error parsing trusted device keys")? - }; - let trusted_device_keys = X5Bag::with_certs(trusted_device_keys) - .context("Error building trusted device keys X5Bag")?; + // Load trusted CA certs for device certificate chain verification + let trusted_device_keys = settings + .trusted_device_keys_path + .as_ref() + .map(|path| -> Result { + let trusted_device_keys = { + let contents = std::fs::read(path) + .with_context(|| format!("Error reading trusted device keys at {}", &path))?; + X509::stack_from_pem(&contents).context("Error parsing trusted device keys")? + }; + + X5Bag::with_certs(trusted_device_keys) + .context("Error building trusted device keys X5Bag") + }) + .transpose() + .context("Error loading trusted device keys")?; // Our private key let owner_key = load_private_key(&settings.owner_private_key_path).with_context(|| { diff --git a/util/src/servers/configuration/owner_onboarding_server.rs b/util/src/servers/configuration/owner_onboarding_server.rs index c5c065997..33f80dee0 100644 --- a/util/src/servers/configuration/owner_onboarding_server.rs +++ b/util/src/servers/configuration/owner_onboarding_server.rs @@ -15,7 +15,7 @@ pub struct OwnerOnboardingServerSettings { pub session_store_driver: StoreConfig, // Trusted keys - pub trusted_device_keys_path: AbsolutePathBuf, + pub trusted_device_keys_path: Option, // Our private owner key pub owner_private_key_path: AbsolutePathBuf,