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
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index df71d94..56a8943 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -46,8 +46,9 @@
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 @@
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.
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
index 0d164f1..5355d93 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -23,9 +23,11 @@
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,
};
-pub use android_system_keystore2::aidl::android::system::keystore2::SecurityLevel::SecurityLevel;
+use android_system_keystore2::aidl::android::system::keystore2::{
+ Authorization::Authorization, SecurityLevel::SecurityLevel as KsSecurityLevel,
+};
use anyhow::{Context, Result};
use rusqlite::types::{FromSql, Null, ToSql, ToSqlOutput};
use rusqlite::{Result as SqlResult, Row};
@@ -233,6 +235,18 @@
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
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 09f20bd..0b5889e 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -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 @@
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 @@
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 @@
fn store_new_key(
&self,
key: KeyDescriptor,
+ key_characteristics: KeyCharacteristics,
km_cert_chain: Option<Vec<KmCertificate>>,
blob: ByteArray,
) -> Result<KeyMetadata> {
@@ -107,6 +112,9 @@
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 @@
)
.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 @@
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 @@
&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 @@
&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 @@
&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.")
}
}
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index 82954ca..d0c44e0 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -24,12 +24,15 @@
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 @@
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 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)
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 5ecb47b..66a7e50 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -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 @@
.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()
+}