blob: 8b79be73600cfefaf82d52ea986e69d08d669686 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! The crypt mod contains all the key policy logic for the different operations that can be done
//! with hardware keys. It provides functions for unsealing and formatting zxcrypt as well as
//! unwrapping the actual keys for fxfs. Keeping the policy logic in one place makes it easier to
//! audit.
use anyhow::{bail, Context, Error};
pub mod fxfs;
pub mod zxcrypt;
#[derive(PartialEq)]
pub enum Policy {
Null,
TeeRequired,
TeeTransitional,
TeeOpportunistic,
}
pub async fn get_policy() -> Result<Policy, Error> {
let policy = fuchsia_fs::file::read_in_namespace_to_string("/boot/config/zxcrypt").await;
let policy = match policy {
Ok(policy) => policy,
// In tests, the configuration is found in the same package as fshost.
Err(_) => fuchsia_fs::file::read_in_namespace_to_string("/pkg/config/zxcrypt").await?,
};
match policy.as_ref() {
"null" => Ok(Policy::Null),
"tee" => Ok(Policy::TeeRequired),
"tee-transitional" => Ok(Policy::TeeTransitional),
"tee-opportunistic" => Ok(Policy::TeeOpportunistic),
p => bail!("unrecognized key source policy: {}", p),
}
}
#[derive(Debug)]
enum KeySource {
Null,
Tee,
}
/// Fxfs and zxcrypt have different null keys, so operations have to indicate which is ultimately
/// going to consume the key we produce.
enum KeyConsumer {
/// The null key for fxfs is a 128-bit key with the bytes "zxcrypt" at the beginning and then
/// padded with zeros. This is for legacy reasons - earlier versions of this code picked this
/// key, so we need to continue to use it to avoid wiping everyone's null-key-encrypted fxfs
/// data partitions.
Fxfs,
/// The null key for zxcrypt is a 256-bit key containing all zeros.
Zxcrypt,
}
impl KeySource {
async fn get_key(&self, consumer: KeyConsumer) -> Result<Vec<u8>, Error> {
match self {
KeySource::Null => match consumer {
KeyConsumer::Fxfs => {
let mut key = b"zxcrypt".to_vec();
key.resize(16, 0);
Ok(key)
}
KeyConsumer::Zxcrypt => Ok(vec![0u8; 32]),
},
KeySource::Tee => {
// Regardless of the consumer of this key, the key we retrieve with kms is always
// named "zxcrypt". This is so that old recovery images that might not be aware of
// fxfs can still wipe the data keys during a factory reset.
kms_stateless::get_hardware_derived_key(kms_stateless::KeyInfo::new_zxcrypt())
.await
.context("failed to get hardware key")
}
}
}
}
fn format_sources(policy: Policy) -> Vec<KeySource> {
match policy {
Policy::Null => vec![KeySource::Null],
Policy::TeeRequired => vec![KeySource::Tee],
Policy::TeeTransitional => vec![KeySource::Tee],
Policy::TeeOpportunistic => vec![KeySource::Tee, KeySource::Null],
}
}
fn unseal_sources(policy: Policy) -> Vec<KeySource> {
match policy {
Policy::Null => vec![KeySource::Null],
Policy::TeeRequired => vec![KeySource::Tee],
Policy::TeeTransitional => vec![KeySource::Tee, KeySource::Null],
Policy::TeeOpportunistic => vec![KeySource::Tee, KeySource::Null],
}
}