Skip to content

Commit

Permalink
feat(owner-onboarding-server): verify device certificate chain
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
mmartinv committed Apr 4, 2024
1 parent a9baf72 commit 32c6a26
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 19 deletions.
4 changes: 2 additions & 2 deletions HOWTO.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions admin-tool/src/aio/configure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
)
Expand Down
50 changes: 38 additions & 12 deletions owner-onboarding-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ mod handlers;

pub(crate) struct OwnerServiceUD {
// Trusted keys
#[allow(dead_code)]
trusted_device_keys: X5Bag,
trusted_device_keys: Option<X5Bag>,

// Stores
ownership_voucher_store: Box<
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -210,6 +211,7 @@ async fn report_ov_to_rendezvous(
owner_addresses: &[TO2AddressEntry],
owner_key: &PKey<Private>,
registration_period: u32,
trusted_device_keys: &Option<X5Bag>,
) -> Result<u32> {
let ov_header = ov.header();
if ov_header.protocol_version() != ProtocolVersion::Version1_1 {
Expand All @@ -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()
Expand Down Expand Up @@ -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<X5Bag, anyhow::Error> {
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(|| {
Expand Down
2 changes: 1 addition & 1 deletion util/src/servers/configuration/owner_onboarding_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AbsolutePathBuf>,

// Our private owner key
pub owner_private_key_path: AbsolutePathBuf,
Expand Down

0 comments on commit 32c6a26

Please sign in to comment.