Keystore 2.0: Store key parameters
We now store key parameters in the database and returns sets of authorizations to the keystore client's. We also switched to mostly using the SecurityLevel type from the KeyMint AIDL spec, rather then the temporary one from the Keystore 2.0 AIDL spec. Test: This enables some of the CTS test e.g. from atest android.keystore.cts.CipherTest Change-Id: I0a13063b397a5ad835fecea0e6b44a98845c05be
This commit is contained in:
parent
85d4793fe8
commit
04b0283254
5 changed files with 93 additions and 20 deletions
|
@ -46,8 +46,9 @@ use crate::key_parameter::{KeyParameter, SqlField, Tag};
|
|||
use crate::permission::KeyPermSet;
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
|
||||
use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel;
|
||||
use android_system_keystore2::aidl::android::system::keystore2::{
|
||||
Domain::Domain, KeyDescriptor::KeyDescriptor, SecurityLevel::SecurityLevel,
|
||||
Domain::Domain, KeyDescriptor::KeyDescriptor,
|
||||
};
|
||||
|
||||
#[cfg(not(test))]
|
||||
|
@ -135,6 +136,14 @@ impl KeyEntry {
|
|||
pub fn sec_level(&self) -> SecurityLevel {
|
||||
self.sec_level
|
||||
}
|
||||
/// Exposes the key parameters of this key entry.
|
||||
pub fn key_parameters(&self) -> &Vec<KeyParameter> {
|
||||
&self.parameters
|
||||
}
|
||||
/// Consumes this key entry and extracts the keyparameters from it.
|
||||
pub fn into_key_parameters(self) -> Vec<KeyParameter> {
|
||||
self.parameters
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates the sub component of a key entry for persistent storage.
|
||||
|
|
|
@ -23,9 +23,11 @@ pub use android_hardware_keymint::aidl::android::hardware::keymint::{
|
|||
Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
|
||||
HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
|
||||
KeyParameter::KeyParameter as KmKeyParameter, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
|
||||
Tag::Tag,
|
||||
SecurityLevel::SecurityLevel, Tag::Tag,
|
||||
};
|
||||
use android_system_keystore2::aidl::android::system::keystore2::{
|
||||
Authorization::Authorization, SecurityLevel::SecurityLevel as KsSecurityLevel,
|
||||
};
|
||||
pub use android_system_keystore2::aidl::android::system::keystore2::SecurityLevel::SecurityLevel;
|
||||
use anyhow::{Context, Result};
|
||||
use rusqlite::types::{FromSql, Null, ToSql, ToSqlOutput};
|
||||
use rusqlite::{Result as SqlResult, Row};
|
||||
|
@ -233,6 +235,18 @@ impl KeyParameter {
|
|||
pub fn security_level(&self) -> &SecurityLevel {
|
||||
&self.security_level
|
||||
}
|
||||
|
||||
/// An authorization is a KeyParameter with an associated security level that is used
|
||||
/// to convey the key characteristics to keystore clients. This function consumes
|
||||
/// an internal KeyParameter representation to produce the Authorization wire type.
|
||||
pub fn into_authorization(self) -> Authorization {
|
||||
Authorization {
|
||||
securityLevel: KsSecurityLevel(self.security_level.0),
|
||||
keyParameter: crate::utils::keyparam_km_to_ks(
|
||||
&self.key_parameter_value.convert_to_wire(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This struct is defined to postpone converting rusqlite column value to the
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
use android_hardware_keymint::aidl::android::hardware::keymint::{
|
||||
Algorithm::Algorithm, ByteArray::ByteArray, Certificate::Certificate as KmCertificate,
|
||||
IKeyMintDevice::IKeyMintDevice, KeyCharacteristics::KeyCharacteristics, KeyFormat::KeyFormat,
|
||||
KeyParameter::KeyParameter as KmParam, KeyPurpose::KeyPurpose, Tag::Tag,
|
||||
KeyParameter::KeyParameter as KmParam, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
|
||||
Tag::Tag,
|
||||
};
|
||||
use android_system_keystore2::aidl::android::system::keystore2::{
|
||||
AuthenticatorSpec::AuthenticatorSpec, AuthenticatorType::AuthenticatorType,
|
||||
|
@ -27,10 +28,9 @@ use android_system_keystore2::aidl::android::system::keystore2::{
|
|||
IKeystoreOperation::IKeystoreOperation, IKeystoreSecurityLevel::BnKeystoreSecurityLevel,
|
||||
IKeystoreSecurityLevel::IKeystoreSecurityLevel, KeyDescriptor::KeyDescriptor,
|
||||
KeyMetadata::KeyMetadata, KeyParameter::KeyParameter, KeyParameters::KeyParameters,
|
||||
SecurityLevel::SecurityLevel,
|
||||
SecurityLevel::SecurityLevel as KsSecurityLevel,
|
||||
};
|
||||
|
||||
use crate::error::{self, map_km_error, map_or_log_err, Error, ErrorCode};
|
||||
use crate::globals::DB;
|
||||
use crate::permission::KeyPerm;
|
||||
use crate::utils::{check_key_permission, keyparam_km_to_ks, keyparam_ks_to_km, Asp};
|
||||
|
@ -39,6 +39,10 @@ use crate::{
|
|||
operation::KeystoreOperation,
|
||||
operation::OperationDb,
|
||||
};
|
||||
use crate::{
|
||||
error::{self, map_km_error, map_or_log_err, Error, ErrorCode},
|
||||
utils::key_characteristics_to_internal,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use binder::{IBinder, Interface, ThreadState};
|
||||
|
||||
|
@ -83,6 +87,7 @@ impl KeystoreSecurityLevel {
|
|||
fn store_new_key(
|
||||
&self,
|
||||
key: KeyDescriptor,
|
||||
key_characteristics: KeyCharacteristics,
|
||||
km_cert_chain: Option<Vec<KmCertificate>>,
|
||||
blob: ByteArray,
|
||||
) -> Result<KeyMetadata> {
|
||||
|
@ -107,6 +112,9 @@ impl KeystoreSecurityLevel {
|
|||
None => (None, None),
|
||||
};
|
||||
|
||||
let key_parameters =
|
||||
key_characteristics_to_internal(key_characteristics, self.security_level);
|
||||
|
||||
let key = match key.domain {
|
||||
Domain::BLOB => {
|
||||
KeyDescriptor { domain: Domain::BLOB, blob: Some(blob.data), ..Default::default() }
|
||||
|
@ -137,6 +145,8 @@ impl KeystoreSecurityLevel {
|
|||
)
|
||||
.context("Trying to insert cert chain blob.")?;
|
||||
}
|
||||
db.insert_keyparameter(key_id, &key_parameters)
|
||||
.context("Trying to insert key parameters.")?;
|
||||
match &key.alias {
|
||||
Some(alias) => db
|
||||
.rebind_alias(key_id, alias, key.domain, key.nspace)
|
||||
|
@ -158,10 +168,10 @@ impl KeystoreSecurityLevel {
|
|||
|
||||
Ok(KeyMetadata {
|
||||
key,
|
||||
keySecurityLevel: self.security_level,
|
||||
keySecurityLevel: KsSecurityLevel(self.security_level.0),
|
||||
certificate: cert,
|
||||
certificateChain: cert_chain,
|
||||
// TODO initialize the authorizations.
|
||||
authorizations: crate::utils::key_parameters_to_authorizations(key_parameters),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
@ -360,7 +370,8 @@ impl KeystoreSecurityLevel {
|
|||
&mut certificate_chain,
|
||||
))?;
|
||||
|
||||
self.store_new_key(key, Some(certificate_chain), blob).context("In generate_key.")
|
||||
self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
|
||||
.context("In generate_key.")
|
||||
}
|
||||
|
||||
fn import_key(
|
||||
|
@ -416,7 +427,8 @@ impl KeystoreSecurityLevel {
|
|||
&mut certificate_chain,
|
||||
))?;
|
||||
|
||||
self.store_new_key(key, Some(certificate_chain), blob).context("In import_key.")
|
||||
self.store_new_key(key, key_characteristics, Some(certificate_chain), blob)
|
||||
.context("In import_key.")
|
||||
}
|
||||
|
||||
fn import_wrapped_key(
|
||||
|
@ -512,7 +524,7 @@ impl KeystoreSecurityLevel {
|
|||
&mut key_characteristics,
|
||||
))?;
|
||||
|
||||
self.store_new_key(key, None, blob).context("In import_wrapped_key.")
|
||||
self.store_new_key(key, key_characteristics, None, blob).context("In import_wrapped_key.")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,12 +24,15 @@ use crate::globals::DB;
|
|||
use crate::permission;
|
||||
use crate::permission::KeyPerm;
|
||||
use crate::security_level::KeystoreSecurityLevel;
|
||||
use crate::utils::{check_grant_permission, check_key_permission, Asp};
|
||||
use crate::utils::{
|
||||
check_grant_permission, check_key_permission, key_parameters_to_authorizations, Asp,
|
||||
};
|
||||
use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel;
|
||||
use android_system_keystore2::aidl::android::system::keystore2::{
|
||||
Domain::Domain, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
|
||||
IKeystoreService::BnKeystoreService, IKeystoreService::IKeystoreService,
|
||||
KeyDescriptor::KeyDescriptor, KeyEntryResponse::KeyEntryResponse, KeyMetadata::KeyMetadata,
|
||||
SecurityLevel::SecurityLevel,
|
||||
SecurityLevel::SecurityLevel as KsSecurityLevel,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use binder::{IBinder, Interface, ThreadState};
|
||||
|
@ -95,10 +98,10 @@ impl KeystoreService {
|
|||
nspace: key_entry.id(),
|
||||
..Default::default()
|
||||
},
|
||||
keySecurityLevel: key_entry.sec_level(),
|
||||
keySecurityLevel: KsSecurityLevel(key_entry.sec_level().0),
|
||||
certificate: key_entry.take_cert(),
|
||||
certificateChain: key_entry.take_cert_chain(),
|
||||
// TODO add key characteristics here.
|
||||
authorizations: key_parameters_to_authorizations(key_entry.into_key_parameters()),
|
||||
..Default::default()
|
||||
},
|
||||
})
|
||||
|
@ -191,9 +194,9 @@ impl binder::Interface for KeystoreService {}
|
|||
impl IKeystoreService for KeystoreService {
|
||||
fn getSecurityLevel(
|
||||
&self,
|
||||
security_level: SecurityLevel,
|
||||
security_level: KsSecurityLevel,
|
||||
) -> binder::public_api::Result<Box<dyn IKeystoreSecurityLevel>> {
|
||||
map_or_log_err(self.get_security_level(security_level), Ok)
|
||||
map_or_log_err(self.get_security_level(SecurityLevel(security_level.0)), Ok)
|
||||
}
|
||||
fn getKeyEntry(&self, key: &KeyDescriptor) -> binder::public_api::Result<KeyEntryResponse> {
|
||||
map_or_log_err(self.get_key_entry(key), Ok)
|
||||
|
|
|
@ -15,14 +15,15 @@
|
|||
//! This module implements utility functions used by the Keystore 2.0 service
|
||||
//! implementation.
|
||||
|
||||
use crate::error::Error;
|
||||
use crate::permission;
|
||||
use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
|
||||
use crate::{error::Error, key_parameter::KeyParameterValue};
|
||||
use android_hardware_keymint::aidl::android::hardware::keymint::{
|
||||
KeyParameter::KeyParameter as KmParam, Tag::Tag,
|
||||
KeyCharacteristics::KeyCharacteristics, KeyParameter::KeyParameter as KmParam,
|
||||
SecurityLevel::SecurityLevel, Tag::Tag,
|
||||
};
|
||||
use android_system_keystore2::aidl::android::system::keystore2::{
|
||||
KeyDescriptor::KeyDescriptor, KeyParameter::KeyParameter,
|
||||
Authorization::Authorization, KeyDescriptor::KeyDescriptor, KeyParameter::KeyParameter,
|
||||
};
|
||||
use anyhow::{anyhow, Context};
|
||||
use binder::{FromIBinder, SpIBinder, ThreadState};
|
||||
|
@ -136,3 +137,37 @@ impl Asp {
|
|||
.map_err(|e| anyhow!(format!("get_interface failed with error code {:?}", e)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a set of key characteristics as returned from KeyMint into the internal
|
||||
/// representation of the keystore service.
|
||||
/// The parameter `hw_security_level` indicates which security level shall be used for
|
||||
/// parameters found in the hardware enforced parameter list.
|
||||
pub fn key_characteristics_to_internal(
|
||||
key_characteristics: KeyCharacteristics,
|
||||
hw_security_level: SecurityLevel,
|
||||
) -> Vec<crate::key_parameter::KeyParameter> {
|
||||
key_characteristics
|
||||
.hardwareEnforced
|
||||
.into_iter()
|
||||
.map(|aidl_kp| {
|
||||
crate::key_parameter::KeyParameter::new(
|
||||
KeyParameterValue::convert_from_wire(aidl_kp),
|
||||
hw_security_level,
|
||||
)
|
||||
})
|
||||
.chain(key_characteristics.softwareEnforced.into_iter().map(|aidl_kp| {
|
||||
crate::key_parameter::KeyParameter::new(
|
||||
KeyParameterValue::convert_from_wire(aidl_kp),
|
||||
SecurityLevel::SOFTWARE,
|
||||
)
|
||||
}))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Converts a set of key characteristics from the internal representation into a set of
|
||||
/// Authorizations as they are used to convey key characteristics to the clients of keystore.
|
||||
pub fn key_parameters_to_authorizations(
|
||||
parameters: Vec<crate::key_parameter::KeyParameter>,
|
||||
) -> Vec<Authorization> {
|
||||
parameters.into_iter().map(|p| p.into_authorization()).collect()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue