diff options
Diffstat (limited to 'keystore2')
-rw-r--r-- | keystore2/Android.bp | 1 | ||||
-rw-r--r-- | keystore2/src/database.rs | 2 | ||||
-rw-r--r-- | keystore2/src/super_key.rs | 92 | ||||
-rw-r--r-- | keystore2/src/utils.rs | 2 |
4 files changed, 57 insertions, 40 deletions
diff --git a/keystore2/Android.bp b/keystore2/Android.bp index 03dfd458..e59b6f24 100644 --- a/keystore2/Android.bp +++ b/keystore2/Android.bp @@ -42,6 +42,7 @@ rust_defaults { "android.security.metrics-rust", "android.security.rkp_aidl-rust", "libaconfig_android_hardware_biometrics_rust", + "libandroid_security_flags_rust", "libanyhow", "libbinder_rs", "libkeystore2_aaid-rust", diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs index 9d2da8cf..83963f9d 100644 --- a/keystore2/src/database.rs +++ b/keystore2/src/database.rs @@ -4890,11 +4890,13 @@ pub mod tests { let key_name_enc = SuperKeyType { alias: "test_super_key_1", algorithm: SuperEncryptionAlgorithm::Aes256Gcm, + name: "test_super_key_1", }; let key_name_nonenc = SuperKeyType { alias: "test_super_key_2", algorithm: SuperEncryptionAlgorithm::Aes256Gcm, + name: "test_super_key_2", }; // Install two super keys. diff --git a/keystore2/src/super_key.rs b/keystore2/src/super_key.rs index 128cf4ca..898a8c2c 100644 --- a/keystore2/src/super_key.rs +++ b/keystore2/src/super_key.rs @@ -78,26 +78,35 @@ pub struct SuperKeyType<'a> { pub alias: &'a str, /// Encryption algorithm pub algorithm: SuperEncryptionAlgorithm, + /// What to call this key in log messages. Not used for anything else. + pub name: &'a str, } /// The user's AfterFirstUnlock super key. This super key is loaded into memory when the user first /// unlocks the device, and it remains in memory until the device reboots. This is used to encrypt /// keys that require user authentication but not an unlocked device. -pub const USER_AFTER_FIRST_UNLOCK_SUPER_KEY: SuperKeyType = - SuperKeyType { alias: "USER_SUPER_KEY", algorithm: SuperEncryptionAlgorithm::Aes256Gcm }; +pub const USER_AFTER_FIRST_UNLOCK_SUPER_KEY: SuperKeyType = SuperKeyType { + alias: "USER_SUPER_KEY", + algorithm: SuperEncryptionAlgorithm::Aes256Gcm, + name: "AfterFirstUnlock super key", +}; + /// The user's UnlockedDeviceRequired symmetric super key. This super key is loaded into memory each /// time the user unlocks the device, and it is cleared from memory each time the user locks the /// device. This is used to encrypt keys that use the UnlockedDeviceRequired key parameter. pub const USER_UNLOCKED_DEVICE_REQUIRED_SYMMETRIC_SUPER_KEY: SuperKeyType = SuperKeyType { alias: "USER_SCREEN_LOCK_BOUND_KEY", algorithm: SuperEncryptionAlgorithm::Aes256Gcm, + name: "UnlockedDeviceRequired symmetric super key", }; + /// The user's UnlockedDeviceRequired asymmetric super key. This is used to allow, while the device /// is locked, the creation of keys that use the UnlockedDeviceRequired key parameter. The private /// part of this key is loaded and cleared when the symmetric key is loaded and cleared. pub const USER_UNLOCKED_DEVICE_REQUIRED_P521_SUPER_KEY: SuperKeyType = SuperKeyType { alias: "USER_SCREEN_LOCK_BOUND_P521_KEY", algorithm: SuperEncryptionAlgorithm::EcdhP521, + name: "UnlockedDeviceRequired asymmetric super key", }; /// Superencryption to apply to a new key. @@ -717,6 +726,47 @@ impl SuperKeyManager { } } + fn create_super_key( + &mut self, + db: &mut KeystoreDB, + user_id: UserId, + key_type: &SuperKeyType, + password: &Password, + reencrypt_with: Option<Arc<SuperKey>>, + ) -> Result<Arc<SuperKey>> { + log::info!("Creating {} for user {}", key_type.name, user_id); + let (super_key, public_key) = match key_type.algorithm { + SuperEncryptionAlgorithm::Aes256Gcm => { + (generate_aes256_key().context(ks_err!("Failed to generate AES-256 key."))?, None) + } + SuperEncryptionAlgorithm::EcdhP521 => { + let key = + ECDHPrivateKey::generate().context(ks_err!("Failed to generate ECDH key"))?; + ( + key.private_key().context(ks_err!("private_key failed"))?, + Some(key.public_key().context(ks_err!("public_key failed"))?), + ) + } + }; + // Derive an AES-256 key from the password and re-encrypt the super key before we insert it + // in the database. + let (encrypted_super_key, blob_metadata) = + Self::encrypt_with_password(&super_key, password).context(ks_err!())?; + let mut key_metadata = KeyMetaData::new(); + if let Some(pk) = public_key { + key_metadata.add(KeyMetaEntry::Sec1PublicKey(pk)); + } + let key_entry = db + .store_super_key(user_id, key_type, &encrypted_super_key, &blob_metadata, &key_metadata) + .context(ks_err!("Failed to store super key."))?; + Ok(Arc::new(SuperKey { + algorithm: key_type.algorithm, + key: super_key, + id: SuperKeyIdentifier::DatabaseId(key_entry.id()), + reencrypt_with, + })) + } + /// Fetch a superencryption key from the database, or create it if it doesn't already exist. /// When this is called, the caller must hold the lock on the SuperKeyManager. /// So it's OK that the check and creation are different DB transactions. @@ -737,43 +787,7 @@ impl SuperKeyManager { reencrypt_with, )?) } else { - let (super_key, public_key) = match key_type.algorithm { - SuperEncryptionAlgorithm::Aes256Gcm => ( - generate_aes256_key().context(ks_err!("Failed to generate AES 256 key."))?, - None, - ), - SuperEncryptionAlgorithm::EcdhP521 => { - let key = ECDHPrivateKey::generate() - .context(ks_err!("Failed to generate ECDH key"))?; - ( - key.private_key().context(ks_err!("private_key failed"))?, - Some(key.public_key().context(ks_err!("public_key failed"))?), - ) - } - }; - // Derive an AES256 key from the password and re-encrypt the super key - // before we insert it in the database. - let (encrypted_super_key, blob_metadata) = - Self::encrypt_with_password(&super_key, password).context(ks_err!())?; - let mut key_metadata = KeyMetaData::new(); - if let Some(pk) = public_key { - key_metadata.add(KeyMetaEntry::Sec1PublicKey(pk)); - } - let key_entry = db - .store_super_key( - user_id, - key_type, - &encrypted_super_key, - &blob_metadata, - &key_metadata, - ) - .context(ks_err!("Failed to store super key."))?; - Ok(Arc::new(SuperKey { - algorithm: key_type.algorithm, - key: super_key, - id: SuperKeyIdentifier::DatabaseId(key_entry.id()), - reencrypt_with, - })) + self.create_super_key(db, user_id, key_type, password, reencrypt_with) } } diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs index f028491a..4fd9c8dd 100644 --- a/keystore2/src/utils.rs +++ b/keystore2/src/utils.rs @@ -269,7 +269,7 @@ pub fn get_current_time_in_milliseconds() -> i64 { let mut current_time = libc::timespec { tv_sec: 0, tv_nsec: 0 }; // SAFETY: The pointer is valid because it comes from a reference, and clock_gettime doesn't // retain it beyond the call. - unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_RAW, &mut current_time) }; + unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut current_time) }; current_time.tv_sec as i64 * 1000 + (current_time.tv_nsec as i64 / 1_000_000) } |