Merge changes I924d6fc8,Iee20a2b1,I4070aade,I55331da0 into main
* changes:
hwcryptohal: Service delegator fixes
hwcryptohal: Adding maps cleanup
hwcryptohal: Adding hwcrypto operations tests
hwcryptohal: Adding hwcrypto operations to hwcrypto service
diff --git a/security/see/hwcrypto/aidl/vts/functional/Android.bp b/security/see/hwcrypto/aidl/vts/functional/Android.bp
index 2aea077..eb2eba1 100644
--- a/security/see/hwcrypto/aidl/vts/functional/Android.bp
+++ b/security/see/hwcrypto/aidl/vts/functional/Android.bp
@@ -65,3 +65,19 @@
"vts",
],
}
+
+rust_test {
+ name: "VtsAidlHwCryptoOperationsTests",
+ srcs: ["hwcrypto_operations_tests.rs"],
+ require_root: true,
+ defaults: [
+ "hw_crypto_hal_aidl_rust_defaults",
+ ],
+ rustlibs: [
+ "libhwcryptohal_vts_test",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/security/see/hwcrypto/aidl/vts/functional/hwcrypto_operations_tests.rs b/security/see/hwcrypto/aidl/vts/functional/hwcrypto_operations_tests.rs
new file mode 100644
index 0000000..521fb73
--- /dev/null
+++ b/security/see/hwcrypto/aidl/vts/functional/hwcrypto_operations_tests.rs
@@ -0,0 +1,586 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! HwCryptoOperations tests.
+
+use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::types::{
+ AesKey::AesKey, ExplicitKeyMaterial::ExplicitKeyMaterial, KeyType::KeyType, KeyLifetime::KeyLifetime,
+ KeyUse::KeyUse, OperationData::OperationData, HmacOperationParameters::HmacOperationParameters,
+ SymmetricOperationParameters::SymmetricOperationParameters, SymmetricOperation::SymmetricOperation,
+ HmacKey::HmacKey, CipherModeParameters::CipherModeParameters, AesCipherMode::AesCipherMode,
+ SymmetricCryptoParameters::SymmetricCryptoParameters,
+};
+use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{
+ KeyPolicy::KeyPolicy,CryptoOperation::CryptoOperation,CryptoOperationSet::CryptoOperationSet,
+ OperationParameters::OperationParameters, PatternParameters::PatternParameters,
+};
+
+#[test]
+fn test_hwcrypto_key_operations_connection() {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+ .expect("Couldn't get back a hwcryptokey binder object");
+ let hw_crypto_operations = hw_crypto_key.getHwCryptoOperations();
+ assert!(hw_crypto_operations.is_ok(), "Couldn't get back a hwcrypto operations binder object");
+}
+
+#[test]
+fn test_hwcrypto_key_operations_simple_aes_test() {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+ .expect("Couldn't get back a hwcryptokey binder object");
+ let hw_crypto_operations = hw_crypto_key
+ .getHwCryptoOperations()
+ .expect("Couldn't get back a hwcryptokey operations binder object");
+ let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+ let policy = KeyPolicy {
+ usage: KeyUse::ENCRYPT_DECRYPT,
+ keyLifetime: KeyLifetime::PORTABLE,
+ keyPermissions: Vec::new(),
+ keyManagementKey: false,
+ keyType: KeyType::AES_128_CBC_PKCS7_PADDING,
+ };
+ let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+ let nonce = [0u8; 16];
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::ENCRYPT;
+ let sym_op_params =
+ SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ let input_data = OperationData::DataBuffer("string to be encrypted".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ let mut op_result = hw_crypto_operations
+ .processCommandList(&mut crypto_sets)
+ .expect("couldn't process commands");
+ // Extracting the vector from the command list because of ownership
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+ let context = op_result.remove(0).context;
+ // Separating the finish call on a different command set to test the returned context
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(encrypted_data);
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+
+ // Decrypting
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::DECRYPT;
+ let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+ // Extracting the vector from the command list because of ownership
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+ let decrypted_msg =
+ String::from_utf8(decrypted_data).expect("couldn't decode received message");
+ assert_eq!(decrypted_msg, "string to be encrypted", "couldn't retrieve original message");
+}
+
+#[test]
+fn test_hwcrypto_key_operations_simple_hmac_test() {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+ .expect("Couldn't get back a hwcryptokey binder object");
+ let hw_crypto_operations = hw_crypto_key
+ .getHwCryptoOperations()
+ .expect("Couldn't get back a hwcryptokey operations binder object");
+ let clear_key = ExplicitKeyMaterial::Hmac(HmacKey::Sha256([0; 32]));
+ let policy = KeyPolicy {
+ usage: KeyUse::SIGN,
+ keyLifetime: KeyLifetime::PORTABLE,
+ keyPermissions: Vec::new(),
+ keyManagementKey: false,
+ keyType: KeyType::HMAC_SHA256,
+ };
+ let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+ let hmac_parameters = HmacOperationParameters { key: Some(key.clone()) };
+ let op_parameters = OperationParameters::Hmac(hmac_parameters);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_parameters));
+ let input_data = OperationData::DataBuffer("text to be mac'ed".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+ // Extracting the vector from the command list because of ownership
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(mac)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+
+ //Getting a second mac to compare
+ let hmac_parameters = HmacOperationParameters { key: Some(key) };
+ let op_parameters = OperationParameters::Hmac(hmac_parameters);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_parameters));
+ let input_data = OperationData::DataBuffer("text to be mac'ed".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+ // Extracting the vector from the command list because of ownership
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(mac2)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+ assert_eq!(mac, mac2, "got a different mac");
+}
+
+#[test]
+fn test_hwcrypto_key_operations_aes_simple_cbcs_test_non_block_multiple() {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+ .expect("Couldn't get back a hwcryptokey binder object");
+ let hw_crypto_operations = hw_crypto_key
+ .getHwCryptoOperations()
+ .expect("Couldn't get back a hwcryptokey operations binder object");
+
+ let usage = KeyUse::ENCRYPT_DECRYPT;
+ let key_type = KeyType::AES_128_CBC_NO_PADDING;
+ let policy = KeyPolicy {
+ usage,
+ keyLifetime: KeyLifetime::PORTABLE,
+ keyPermissions: Vec::new(),
+ keyType: key_type,
+ keyManagementKey: false,
+ };
+ let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+ let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+ let nonce = [0u8; 16];
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::ENCRYPT;
+ let sym_op_params =
+ SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+ numberBlocksProcess: 1,
+ numberBlocksCopy: 0,
+ }));
+ let input_data =
+ OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let input_data =
+ OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let input_data = OperationData::DataBuffer("unencrypted".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+
+ let clear_encrypted_msg =
+ String::from_utf8(encrypted_data[encrypted_data.len() - "unencrypted".len()..].to_vec())
+ .expect("couldn't decode message");
+ assert_eq!(clear_encrypted_msg, "unencrypted");
+
+ // Decrypting
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::DECRYPT;
+ let sym_op_params =
+ SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+ numberBlocksProcess: 1,
+ numberBlocksCopy: 0,
+ }));
+ cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+ let decrypted_msg =
+ String::from_utf8(decrypted_data).expect("couldn't decode received message");
+ assert_eq!(
+ decrypted_msg,
+ "encryption data.0123456789abcdeffedcba9876543210\
+ 0123456789abcdefunencrypted",
+ "couldn't retrieve original message"
+ );
+}
+
+#[test]
+fn test_hwcrypto_key_operations_aes_simple_all_encrypted_cbcs_test() {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+ .expect("Couldn't get back a hwcryptokey binder object");
+ let hw_crypto_operations = hw_crypto_key
+ .getHwCryptoOperations()
+ .expect("Couldn't get back a hwcryptokey operations binder object");
+
+ let usage = KeyUse::ENCRYPT_DECRYPT;
+ let key_type = KeyType::AES_128_CBC_NO_PADDING;
+ let policy = KeyPolicy {
+ usage,
+ keyLifetime: KeyLifetime::PORTABLE,
+ keyPermissions: Vec::new(),
+ keyType: key_type,
+ keyManagementKey: false,
+ };
+ let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+ let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+ let nonce = [0u8; 16];
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::ENCRYPT;
+ let sym_op_params =
+ SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+ numberBlocksProcess: 1,
+ numberBlocksCopy: 0,
+ }));
+ let input_data =
+ OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let input_data =
+ OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+
+ // Checking that encrypting with patter 0,0 is equivalent to pattern 1,0
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::ENCRYPT;
+ let sym_op_params =
+ SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+ numberBlocksProcess: 0,
+ numberBlocksCopy: 0,
+ }));
+ let input_data =
+ OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let input_data =
+ OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data1)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+ assert_eq!(encrypted_data, encrypted_data1, "encrypted data should match");
+
+ // Decrypting
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::DECRYPT;
+ let sym_op_params =
+ SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+ let decrypted_msg =
+ String::from_utf8(decrypted_data).expect("couldn't decode received message");
+ assert_eq!(
+ decrypted_msg,
+ "encryption data.0123456789abcdeffedcba9876543210\
+ 0123456789abcdef",
+ "couldn't retrieve original message"
+ );
+}
+
+#[test]
+fn check_cbcs_wrong_key_types() {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+ .expect("Couldn't get back a hwcryptokey binder object");
+ let hw_crypto_operations = hw_crypto_key
+ .getHwCryptoOperations()
+ .expect("Couldn't get back a hwcryptokey operations binder object");
+
+ let usage = KeyUse::ENCRYPT_DECRYPT;
+ let key_type = KeyType::AES_128_CBC_PKCS7_PADDING;
+ let policy = KeyPolicy {
+ usage,
+ keyLifetime: KeyLifetime::PORTABLE,
+ keyPermissions: Vec::new(),
+ keyType: key_type,
+ keyManagementKey: false,
+ };
+ let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+ let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+ let nonce = [0u8; 16];
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::ENCRYPT;
+ let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+ numberBlocksProcess: 1,
+ numberBlocksCopy: 9,
+ }));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ let process_result = hw_crypto_operations.processCommandList(&mut crypto_sets);
+ assert!(process_result.is_err(), "Should not be able to use cbcs mode with this key type");
+
+ let policy = KeyPolicy {
+ usage,
+ keyLifetime: KeyLifetime::PORTABLE,
+ keyPermissions: Vec::new(),
+ keyType: KeyType::AES_256_CBC_NO_PADDING,
+ keyManagementKey: false,
+ };
+ let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes256([0; 32]));
+ let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+ numberBlocksProcess: 1,
+ numberBlocksCopy: 9,
+ }));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ let process_result = hw_crypto_operations.processCommandList(&mut crypto_sets);
+
+ assert!(process_result.is_err(), "Should not be able to use cbcs mode with this key type");
+}
+
+#[test]
+fn aes_simple_cbcs_test() {
+ let hw_crypto_key = hwcryptohal_vts_test::get_hwcryptokey()
+ .expect("Couldn't get back a hwcryptokey binder object");
+ let hw_crypto_operations = hw_crypto_key
+ .getHwCryptoOperations()
+ .expect("Couldn't get back a hwcryptokey operations binder object");
+
+ let usage = KeyUse::ENCRYPT_DECRYPT;
+ let key_type = KeyType::AES_128_CBC_NO_PADDING;
+ let policy = KeyPolicy {
+ usage,
+ keyLifetime: KeyLifetime::PORTABLE,
+ keyPermissions: Vec::new(),
+ keyType: key_type,
+ keyManagementKey: false,
+ };
+ let clear_key = ExplicitKeyMaterial::Aes(AesKey::Aes128([0; 16]));
+ let key = hw_crypto_key.importClearKey(&clear_key, &policy).expect("couldn't import clear key");
+
+ let nonce = [0u8; 16];
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::ENCRYPT;
+ let sym_op_params =
+ SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+ numberBlocksProcess: 1,
+ numberBlocksCopy: 9,
+ }));
+ let input_data =
+ OperationData::DataBuffer("encryption data.0123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let input_data =
+ OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let input_data =
+ OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let input_data =
+ OperationData::DataBuffer("fedcba98765432100123456789abcdef".as_bytes().to_vec());
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ let input_data = OperationData::DataBuffer(
+ "fedcba98765432100123456789abcdefProtectedSection".as_bytes().to_vec(),
+ );
+ cmd_list.push(CryptoOperation::DataInput(input_data));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+ let clear_encrypted_msg =
+ String::from_utf8(encrypted_data[16..encrypted_data.len() - 16].to_vec())
+ .expect("couldn't decode received message");
+ assert_eq!(
+ clear_encrypted_msg,
+ "0123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210\
+ 0123456789abcdeffedcba98765432100123456789abcdeffedcba98765432100123456789abcdef",
+ "couldn't retrieve clear portion"
+ );
+
+ // Decrypting
+ let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters {
+ nonce: nonce.into(),
+ }));
+ let direction = SymmetricOperation::DECRYPT;
+ let sym_op_params =
+ SymmetricOperationParameters { key: Some(key.clone()), direction, parameters };
+ let op_params = OperationParameters::SymmetricCrypto(sym_op_params);
+ let mut cmd_list = Vec::<CryptoOperation>::new();
+ let data_output = OperationData::DataBuffer(Vec::new());
+ cmd_list.push(CryptoOperation::DataOutput(data_output));
+ cmd_list.push(CryptoOperation::SetOperationParameters(op_params));
+ cmd_list.push(CryptoOperation::SetPattern(PatternParameters {
+ numberBlocksProcess: 1,
+ numberBlocksCopy: 9,
+ }));
+ cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data)));
+ cmd_list.push(CryptoOperation::Finish(None));
+ let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list };
+ let mut crypto_sets = Vec::new();
+ crypto_sets.push(crypto_op_set);
+ hw_crypto_operations.processCommandList(&mut crypto_sets).expect("couldn't process commands");
+
+ let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) =
+ crypto_sets.remove(0).operations.remove(0)
+ else {
+ panic!("not reachable, we created this object above on the test");
+ };
+ let decrypted_msg =
+ String::from_utf8(decrypted_data).expect("couldn't decode received message");
+ assert_eq!(
+ decrypted_msg,
+ "encryption data.0123456789abcdeffedcba9876543210\
+ 0123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210\
+ 0123456789abcdeffedcba98765432100123456789abcdefProtectedSection",
+ "couldn't retrieve original message"
+ );
+}
diff --git a/security/see/hwcrypto/aidl/vts/functional/lib.rs b/security/see/hwcrypto/aidl/vts/functional/lib.rs
index 81ae3fa..465dde7 100644
--- a/security/see/hwcrypto/aidl/vts/functional/lib.rs
+++ b/security/see/hwcrypto/aidl/vts/functional/lib.rs
@@ -17,61 +17,11 @@
//! VTS test library for HwCrypto functionality.
//! It provides the base clases necessaries to write HwCrypto VTS tests
-#[cfg(target_arch = "x86_64")]
-use anyhow::Context;
use anyhow::Result;
-#[cfg(target_arch = "x86_64")]
-use binder::{ExceptionCode, FromIBinder, IntoBinderResult, ParcelFileDescriptor};
-#[cfg(target_arch = "x86_64")]
-use rpcbinder::RpcSession;
-#[cfg(target_arch = "x86_64")]
-use vsock::VsockStream;
-#[cfg(target_arch = "x86_64")]
-use std::os::fd::{FromRawFd, IntoRawFd};
-#[cfg(target_arch = "x86_64")]
-use std::fs::File;
-#[cfg(target_arch = "x86_64")]
-use std::io::Read;
-#[cfg(target_arch = "x86_64")]
-use rustutils::system_properties;
-#[cfg(target_arch = "aarch64")]
use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::IHwCryptoKey::BpHwCryptoKey;
use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::IHwCryptoKey::IHwCryptoKey;
-#[cfg(target_arch = "x86_64")]
-const HWCRYPTO_SERVICE_PORT: u32 = 4;
-
-/// Local function to connect to service
-#[cfg(target_arch = "x86_64")]
-pub fn connect_service<T: FromIBinder + ?Sized>(
- cid: u32,
- port: u32,
-) -> Result<binder::Strong<T>, binder::StatusCode> {
- RpcSession::new().setup_preconnected_client(|| {
- let mut stream = VsockStream::connect_with_cid_port(cid, port).ok()?;
- let mut buffer = [0];
- let _ = stream.read(&mut buffer);
- // SAFETY: ownership is transferred from stream to f
- let f = unsafe { File::from_raw_fd(stream.into_raw_fd()) };
- Some(ParcelFileDescriptor::new(f).into_raw_fd())
- })
-}
-
-/// Get a HwCryptoKey binder service object using a direct vsock connection
-#[cfg(target_arch = "x86_64")]
-pub fn get_hwcryptokey() -> Result<binder::Strong<dyn IHwCryptoKey>, binder::Status> {
- let cid = system_properties::read("trusty.test_vm.vm_cid")
- .context("couldn't get vm cid")
- .or_binder_exception(ExceptionCode::ILLEGAL_STATE)?
- .ok_or(ExceptionCode::ILLEGAL_STATE)?
- .parse::<u32>()
- .context("couldn't parse vm cid")
- .or_binder_exception(ExceptionCode::ILLEGAL_ARGUMENT)?;
- Ok(connect_service(cid, HWCRYPTO_SERVICE_PORT)?)
-}
-
/// Get a HwCryptoKey binder service object using the service manager
-#[cfg(target_arch = "aarch64")]
pub fn get_hwcryptokey() -> Result<binder::Strong<dyn IHwCryptoKey>, binder::Status> {
let interface_name = <BpHwCryptoKey as IHwCryptoKey>::get_descriptor().to_owned() + "/default";
Ok(binder::get_interface(&interface_name)?)
diff --git a/security/see/hwcrypto/default/hwcryptokeyimpl.h b/security/see/hwcrypto/default/hwcryptokeyimpl.h
index 19be8b4..7d3ade7 100644
--- a/security/see/hwcrypto/default/hwcryptokeyimpl.h
+++ b/security/see/hwcrypto/default/hwcryptokeyimpl.h
@@ -46,30 +46,33 @@
ndk::ScopedAStatus deriveCurrentDicePolicyBoundKey(
const ndk_hwcrypto::IHwCryptoKey::DiceBoundDerivationKey& derivationKey,
- ndk_hwcrypto::IHwCryptoKey::DiceCurrentBoundKeyResult* aidl_return);
+ ndk_hwcrypto::IHwCryptoKey::DiceCurrentBoundKeyResult* aidl_return) override;
ndk::ScopedAStatus deriveDicePolicyBoundKey(
const ndk_hwcrypto::IHwCryptoKey::DiceBoundDerivationKey& derivationKey,
const ::std::vector<uint8_t>& dicePolicyForKeyVersion,
- ndk_hwcrypto::IHwCryptoKey::DiceBoundKeyResult* aidl_return);
+ ndk_hwcrypto::IHwCryptoKey::DiceBoundKeyResult* aidl_return) override;
ndk::ScopedAStatus deriveKey(const ndk_hwcrypto::IHwCryptoKey::DerivedKeyParameters& parameters,
- ndk_hwcrypto::IHwCryptoKey::DerivedKey* aidl_return);
+ ndk_hwcrypto::IHwCryptoKey::DerivedKey* aidl_return) override;
ndk::ScopedAStatus getHwCryptoOperations(
- std::shared_ptr<ndk_hwcrypto::IHwCryptoOperations>* aidl_return);
+ std::shared_ptr<ndk_hwcrypto::IHwCryptoOperations>* aidl_return) override;
- ndk::ScopedAStatus importClearKey(const ndk_hwcrypto::types::ExplicitKeyMaterial& keyMaterial,
- const ndk_hwcrypto::KeyPolicy& newKeyPolicy,
- std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return);
+ ndk::ScopedAStatus importClearKey(
+ const ndk_hwcrypto::types::ExplicitKeyMaterial& keyMaterial,
+ const ndk_hwcrypto::KeyPolicy& newKeyPolicy,
+ std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return) override;
- ndk::ScopedAStatus getCurrentDicePolicy(std::vector<uint8_t>* aidl_return);
+ ndk::ScopedAStatus getCurrentDicePolicy(std::vector<uint8_t>* aidl_return) override;
- ndk::ScopedAStatus keyTokenImport(const ndk_hwcrypto::types::OpaqueKeyToken& requestedKey,
- const ::std::vector<uint8_t>& sealingDicePolicy,
- std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return);
+ ndk::ScopedAStatus keyTokenImport(
+ const ndk_hwcrypto::types::OpaqueKeyToken& requestedKey,
+ const ::std::vector<uint8_t>& sealingDicePolicy,
+ std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return) override;
- ndk::ScopedAStatus getKeyslotData(ndk_hwcrypto::IHwCryptoKey::KeySlot slotId,
- std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return);
+ ndk::ScopedAStatus getKeyslotData(
+ ndk_hwcrypto::IHwCryptoKey::KeySlot slotId,
+ std::shared_ptr<ndk_hwcrypto::IOpaqueKey>* aidl_return) override;
};
template <typename LHP, typename RHP>
@@ -79,9 +82,10 @@
policy.keyLifetime = static_cast<decltype(policy.keyLifetime)>(policyToConvert.keyLifetime);
policy.keyType = static_cast<decltype(policy.keyType)>(policyToConvert.keyType);
policy.keyManagementKey = policyToConvert.keyManagementKey;
+ policy.keyPermissions.reserve(policyToConvert.keyPermissions.size());
for (auto permission : policyToConvert.keyPermissions) {
policy.keyPermissions.push_back(
- std::move(reinterpret_cast<decltype(policy.keyPermissions[0])>(permission)));
+ std::move(static_cast<decltype(policy.keyPermissions)::value_type>(permission)));
}
return policy;
}
diff --git a/security/see/hwcrypto/default/hwcryptolib.cpp b/security/see/hwcrypto/default/hwcryptolib.cpp
index b168707..5babc23 100644
--- a/security/see/hwcrypto/default/hwcryptolib.cpp
+++ b/security/see/hwcrypto/default/hwcryptolib.cpp
@@ -115,11 +115,14 @@
class HwCryptoOperationContextNdk : public ndk_hwcrypto::BnCryptoOperationContext {
private:
sp<cpp_hwcrypto::ICryptoOperationContext> mContext;
+ std::weak_ptr<ndk_hwcrypto::ICryptoOperationContext> self;
public:
HwCryptoOperationContextNdk(sp<cpp_hwcrypto::ICryptoOperationContext> operations)
: mContext(std::move(operations)) {}
+ ~HwCryptoOperationContextNdk() { contextMapping.erase(self); }
+
static std::shared_ptr<HwCryptoOperationContextNdk> Create(
sp<cpp_hwcrypto::ICryptoOperationContext> operations) {
if (operations == nullptr) {
@@ -132,18 +135,18 @@
LOG(ERROR) << "failed to allocate HwCryptoOperationContext";
return nullptr;
}
+ contextNdk->self = contextNdk;
return contextNdk;
}
};
-// TODO: Check refactoring opportunities like returning a Result<cpp_hwcrypto::types::OperationData>
-// once we add the code that uses this function.
-Result<void> setOperationData(const ndk_hwcrypto::types::OperationData& ndkOperationData,
- cpp_hwcrypto::types::OperationData* cppOperationData) {
+std::optional<cpp_hwcrypto::types::OperationData> convertOperationData(
+ const ndk_hwcrypto::types::OperationData& ndkOperationData) {
+ cpp_hwcrypto::types::OperationData cppOperationData = cpp_hwcrypto::types::OperationData();
cpp_hwcrypto::types::MemoryBufferReference cppMemBuffRef;
switch (ndkOperationData.getTag()) {
case ndk_hwcrypto::types::OperationData::dataBuffer:
- cppOperationData->set<cpp_hwcrypto::types::OperationData::dataBuffer>(
+ cppOperationData.set<cpp_hwcrypto::types::OperationData::dataBuffer>(
ndkOperationData.get<ndk_hwcrypto::types::OperationData::dataBuffer>());
break;
case ndk_hwcrypto::types::OperationData::memoryBufferReference:
@@ -155,14 +158,223 @@
ndkOperationData
.get<ndk_hwcrypto::types::OperationData::memoryBufferReference>()
.sizeBytes;
- cppOperationData->set<cpp_hwcrypto::types::OperationData::memoryBufferReference>(
+ cppOperationData.set<cpp_hwcrypto::types::OperationData::memoryBufferReference>(
std::move(cppMemBuffRef));
break;
default:
- // This shouldn't happen with the current definitions
- return ErrnoError() << "received unknown operation data type";
+ LOG(ERROR) << "received unknown operation data type";
+ return std::nullopt;
}
- return {};
+ return cppOperationData;
+}
+
+std::optional<cpp_hwcrypto::PatternParameters> convertPatternParameters(
+ const ndk_hwcrypto::PatternParameters& ndkpatternParameters) {
+ int64_t numberBlocksProcess = ndkpatternParameters.numberBlocksProcess;
+ int64_t numberBlocksCopy = ndkpatternParameters.numberBlocksCopy;
+ if ((numberBlocksProcess < 0) || (numberBlocksCopy < 0)) {
+ LOG(ERROR) << "received invalid pattern parameters";
+ return std::nullopt;
+ }
+ cpp_hwcrypto::PatternParameters patternParameters = cpp_hwcrypto::PatternParameters();
+ patternParameters.numberBlocksProcess = numberBlocksProcess;
+ patternParameters.numberBlocksCopy = numberBlocksCopy;
+ return patternParameters;
+}
+
+std::optional<cpp_hwcrypto::types::SymmetricOperation> convertSymmetricOperation(
+ const ndk_hwcrypto::types::SymmetricOperation& ndkSymmetricOperation) {
+ cpp_hwcrypto::types::SymmetricOperation symmetricOperation =
+ cpp_hwcrypto::types::SymmetricOperation();
+ switch (ndkSymmetricOperation) {
+ case ndk_hwcrypto::types::SymmetricOperation::ENCRYPT:
+ symmetricOperation = cpp_hwcrypto::types::SymmetricOperation::ENCRYPT;
+ break;
+ case ndk_hwcrypto::types::SymmetricOperation::DECRYPT:
+ symmetricOperation = cpp_hwcrypto::types::SymmetricOperation::DECRYPT;
+ break;
+ default:
+ LOG(ERROR) << "invalid symmetric operation type";
+ return std::nullopt;
+ }
+ return symmetricOperation;
+}
+
+cpp_hwcrypto::types::CipherModeParameters convertSymmetricModeParameters(
+ const ndk_hwcrypto::types::CipherModeParameters& ndkcipherModeParameters) {
+ cpp_hwcrypto::types::CipherModeParameters cipherModeParameters =
+ cpp_hwcrypto::types::CipherModeParameters();
+ cipherModeParameters.nonce = ndkcipherModeParameters.nonce;
+ return cipherModeParameters;
+}
+
+cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters convertSymmetricModeParameters(
+ const ndk_hwcrypto::types::AesGcmMode::AesGcmModeParameters& ndkgcmModeParameters) {
+ cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters gcmModeParameters =
+ cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters();
+ gcmModeParameters.nonce = ndkgcmModeParameters.nonce;
+ return gcmModeParameters;
+}
+
+std::optional<cpp_hwcrypto::OperationParameters> convertOperationParameters(
+ const ndk_hwcrypto::OperationParameters& ndkOperationParameters) {
+ cpp_hwcrypto::OperationParameters operationParameters = cpp_hwcrypto::OperationParameters();
+ sp<cpp_hwcrypto::IOpaqueKey> opaqueKey;
+ cpp_hwcrypto::types::HmacOperationParameters hmacParameters =
+ cpp_hwcrypto::types::HmacOperationParameters();
+ std::optional<cpp_hwcrypto::types::SymmetricOperation> cppSymmetricOperation;
+ cpp_hwcrypto::types::CipherModeParameters cipherModeParameters;
+ cpp_hwcrypto::types::AesCipherMode cppAesCipherMode = cpp_hwcrypto::types::AesCipherMode();
+ cpp_hwcrypto::types::SymmetricOperationParameters cppSymmetricOperationParameters =
+ cpp_hwcrypto::types::SymmetricOperationParameters();
+ cpp_hwcrypto::types::SymmetricAuthOperationParameters cppSymmetricAuthOperationParameters =
+ cpp_hwcrypto::types::SymmetricAuthOperationParameters();
+ cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters cppAesGcmModeParameters =
+ cpp_hwcrypto::types::AesGcmMode::AesGcmModeParameters();
+ cpp_hwcrypto::types::AesGcmMode cppAesGcmMode = cpp_hwcrypto::types::AesGcmMode();
+ switch (ndkOperationParameters.getTag()) {
+ case ndk_hwcrypto::OperationParameters::symmetricAuthCrypto:
+ opaqueKey = retrieveCppBinder<cpp_hwcrypto::IOpaqueKey, ndk_hwcrypto::IOpaqueKey,
+ keyMapping>(
+ ndkOperationParameters
+ .get<ndk_hwcrypto::OperationParameters::symmetricAuthCrypto>()
+ .key);
+ if (!opaqueKey) {
+ LOG(ERROR) << "couldn't get aes key";
+ return std::nullopt;
+ }
+ cppSymmetricAuthOperationParameters.key = std::move(opaqueKey);
+ cppSymmetricOperation = convertSymmetricOperation(
+ ndkOperationParameters
+ .get<ndk_hwcrypto::OperationParameters::symmetricAuthCrypto>()
+ .direction);
+ if (!cppSymmetricOperation.has_value()) {
+ LOG(ERROR) << "couldn't get aes direction";
+ return std::nullopt;
+ }
+ cppSymmetricAuthOperationParameters.direction =
+ std::move(cppSymmetricOperation.value());
+ switch (ndkOperationParameters
+ .get<ndk_hwcrypto::OperationParameters::symmetricAuthCrypto>()
+ .parameters.getTag()) {
+ case ndk_hwcrypto::types::SymmetricAuthCryptoParameters::aes:
+ switch (ndkOperationParameters
+ .get<ndk_hwcrypto::OperationParameters::symmetricAuthCrypto>()
+ .parameters
+ .get<ndk_hwcrypto::types::SymmetricAuthCryptoParameters::aes>()
+ .getTag()) {
+ case ndk_hwcrypto::types::AesGcmMode::gcmTag16:
+ cppAesGcmModeParameters = convertSymmetricModeParameters(
+ ndkOperationParameters
+ .get<ndk_hwcrypto::OperationParameters::
+ symmetricAuthCrypto>()
+ .parameters
+ .get<ndk_hwcrypto::types::
+ SymmetricAuthCryptoParameters::aes>()
+ .get<ndk_hwcrypto::types::AesGcmMode::gcmTag16>());
+ cppAesGcmMode.set<cpp_hwcrypto::types::AesGcmMode::gcmTag16>(
+ std::move(cppAesGcmModeParameters));
+ cppSymmetricAuthOperationParameters.parameters
+ .set<cpp_hwcrypto::types::SymmetricAuthCryptoParameters::aes>(
+ std::move(cppAesGcmMode));
+ break;
+ default:
+ LOG(ERROR) << "received invalid aes gcm parameters";
+ return std::nullopt;
+ }
+ break;
+ default:
+ LOG(ERROR) << "received invalid symmetric auth crypto parameters";
+ return std::nullopt;
+ }
+ operationParameters.set<cpp_hwcrypto::OperationParameters::symmetricAuthCrypto>(
+ std::move(cppSymmetricAuthOperationParameters));
+ break;
+ case ndk_hwcrypto::OperationParameters::symmetricCrypto:
+ opaqueKey = retrieveCppBinder<cpp_hwcrypto::IOpaqueKey, ndk_hwcrypto::IOpaqueKey,
+ keyMapping>(
+ ndkOperationParameters.get<ndk_hwcrypto::OperationParameters::symmetricCrypto>()
+ .key);
+ if (!opaqueKey) {
+ LOG(ERROR) << "couldn't get aes key";
+ return std::nullopt;
+ }
+ cppSymmetricOperationParameters.key = std::move(opaqueKey);
+ cppSymmetricOperation = convertSymmetricOperation(
+ ndkOperationParameters.get<ndk_hwcrypto::OperationParameters::symmetricCrypto>()
+ .direction);
+ if (!cppSymmetricOperation.has_value()) {
+ LOG(ERROR) << "couldn't get aes direction";
+ return std::nullopt;
+ }
+ cppSymmetricOperationParameters.direction = std::move(cppSymmetricOperation.value());
+ switch (ndkOperationParameters.get<ndk_hwcrypto::OperationParameters::symmetricCrypto>()
+ .parameters.getTag()) {
+ case ndk_hwcrypto::types::SymmetricCryptoParameters::aes:
+ switch (ndkOperationParameters
+ .get<ndk_hwcrypto::OperationParameters::symmetricCrypto>()
+ .parameters
+ .get<ndk_hwcrypto::types::SymmetricCryptoParameters::aes>()
+ .getTag()) {
+ case ndk_hwcrypto::types::AesCipherMode::cbc:
+ cipherModeParameters = convertSymmetricModeParameters(
+ ndkOperationParameters
+ .get<ndk_hwcrypto::OperationParameters::
+ symmetricCrypto>()
+ .parameters
+ .get<ndk_hwcrypto::types::SymmetricCryptoParameters::
+ aes>()
+ .get<ndk_hwcrypto::types::AesCipherMode::cbc>());
+ cppAesCipherMode.set<cpp_hwcrypto::types::AesCipherMode::cbc>(
+ std::move(cipherModeParameters));
+ cppSymmetricOperationParameters.parameters
+ .set<cpp_hwcrypto::types::SymmetricCryptoParameters::aes>(
+ std::move(cppAesCipherMode));
+ break;
+ case ndk_hwcrypto::types::AesCipherMode::ctr:
+ cipherModeParameters = convertSymmetricModeParameters(
+ ndkOperationParameters
+ .get<ndk_hwcrypto::OperationParameters::
+ symmetricCrypto>()
+ .parameters
+ .get<ndk_hwcrypto::types::SymmetricCryptoParameters::
+ aes>()
+ .get<ndk_hwcrypto::types::AesCipherMode::ctr>());
+ cppAesCipherMode.set<cpp_hwcrypto::types::AesCipherMode::ctr>(
+ std::move(cipherModeParameters));
+ cppSymmetricOperationParameters.parameters
+ .set<cpp_hwcrypto::types::SymmetricCryptoParameters::aes>(
+ std::move(cppAesCipherMode));
+ break;
+ default:
+ LOG(ERROR) << "received invalid aes parameters";
+ return std::nullopt;
+ }
+ break;
+ default:
+ LOG(ERROR) << "received invalid symmetric crypto parameters";
+ return std::nullopt;
+ }
+ operationParameters.set<cpp_hwcrypto::OperationParameters::symmetricCrypto>(
+ std::move(cppSymmetricOperationParameters));
+ break;
+ case ndk_hwcrypto::OperationParameters::hmac:
+ opaqueKey = retrieveCppBinder<cpp_hwcrypto::IOpaqueKey, ndk_hwcrypto::IOpaqueKey,
+ keyMapping>(
+ ndkOperationParameters.get<ndk_hwcrypto::OperationParameters::hmac>().key);
+ if (!opaqueKey) {
+ LOG(ERROR) << "couldn't get hmac key";
+ return std::nullopt;
+ }
+ hmacParameters.key = opaqueKey;
+ operationParameters.set<cpp_hwcrypto::OperationParameters::hmac>(
+ std::move(hmacParameters));
+ break;
+ default:
+ LOG(ERROR) << "received invalid operation parameters";
+ return std::nullopt;
+ }
+ return operationParameters;
}
class HwCryptoOperationsNdk : public ndk_hwcrypto::BnHwCryptoOperations {
@@ -189,19 +401,208 @@
}
ndk::ScopedAStatus processCommandList(
- std::vector<ndk_hwcrypto::CryptoOperationSet>* /*operationSets*/,
- std::vector<ndk_hwcrypto::CryptoOperationResult>* /*aidl_return*/) {
- return ndk::ScopedAStatus::ok();
+ std::vector<ndk_hwcrypto::CryptoOperationSet>* operationSets,
+ std::vector<ndk_hwcrypto::CryptoOperationResult>* aidl_return) {
+ Status status = Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
+ if (operationSets == nullptr) {
+ LOG(ERROR) << "received a null operation set";
+ return convertStatus(status);
+ }
+ if (aidl_return == nullptr) {
+ LOG(ERROR) << "received a null CryptoOperationResult set";
+ return convertStatus(status);
+ }
+ std::vector<cpp_hwcrypto::CryptoOperationResult> binderResult;
+ std::vector<cpp_hwcrypto::CryptoOperationSet> cppOperationSets;
+ for (ndk_hwcrypto::CryptoOperationSet& operationSet : *operationSets) {
+ cpp_hwcrypto::CryptoOperationSet cppSingleOperation =
+ cpp_hwcrypto::CryptoOperationSet();
+ cppSingleOperation.context =
+ retrieveCppBinder<cpp_hwcrypto::ICryptoOperationContext,
+ ndk_hwcrypto::ICryptoOperationContext, contextMapping>(
+ operationSet.context);
+ for (ndk_hwcrypto::CryptoOperation& operation : operationSet.operations) {
+ cpp_hwcrypto::CryptoOperation cppOperation;
+ cpp_hwcrypto::types::Void voidObj;
+ std::optional<cpp_hwcrypto::types::OperationData> cppOperationData;
+ std::optional<cpp_hwcrypto::PatternParameters> cppPatternParameters;
+ std::optional<cpp_hwcrypto::OperationParameters> cppOperationParameters;
+ switch (operation.getTag()) {
+ case ndk_hwcrypto::CryptoOperation::setMemoryBuffer:
+ // TODO: finish this case
+ exit(1);
+ break;
+ case ndk_hwcrypto::CryptoOperation::setOperationParameters:
+ cppOperationParameters = convertOperationParameters(
+ operation.get<
+ ndk_hwcrypto::CryptoOperation::setOperationParameters>());
+ if (cppOperationParameters.has_value()) {
+ cppOperation.set<cpp_hwcrypto::CryptoOperation::setOperationParameters>(
+ std::move(cppOperationParameters.value()));
+ } else {
+ LOG(ERROR) << "couldn't convert operation parameters";
+ return convertStatus(status);
+ }
+ break;
+ case ndk_hwcrypto::CryptoOperation::setPattern:
+ cppPatternParameters = convertPatternParameters(
+ operation.get<ndk_hwcrypto::CryptoOperation::setPattern>());
+ if (cppPatternParameters.has_value()) {
+ cppOperation.set<cpp_hwcrypto::CryptoOperation::setPattern>(
+ std::move(cppPatternParameters.value()));
+ } else {
+ LOG(ERROR) << "couldn't convert pattern parameters";
+ return convertStatus(status);
+ }
+ break;
+ case ndk_hwcrypto::CryptoOperation::copyData:
+ cppOperationData = convertOperationData(
+ operation.get<ndk_hwcrypto::CryptoOperation::copyData>());
+ if (cppOperationData.has_value()) {
+ cppOperation.set<cpp_hwcrypto::CryptoOperation::copyData>(
+ std::move(cppOperationData.value()));
+ } else {
+ LOG(ERROR) << "couldn't convert CryptoOperation::copyData";
+ return convertStatus(status);
+ }
+ break;
+ case ndk_hwcrypto::CryptoOperation::aadInput:
+ cppOperationData = convertOperationData(
+ operation.get<ndk_hwcrypto::CryptoOperation::aadInput>());
+ if (cppOperationData.has_value()) {
+ cppOperation.set<cpp_hwcrypto::CryptoOperation::aadInput>(
+ std::move(cppOperationData.value()));
+ } else {
+ LOG(ERROR) << "couldn't convert CryptoOperation::aadInput";
+ return convertStatus(status);
+ }
+ break;
+ case ndk_hwcrypto::CryptoOperation::dataInput:
+ cppOperationData = convertOperationData(
+ operation.get<ndk_hwcrypto::CryptoOperation::dataInput>());
+ if (cppOperationData.has_value()) {
+ cppOperation.set<cpp_hwcrypto::CryptoOperation::dataInput>(
+ std::move(cppOperationData.value()));
+ } else {
+ LOG(ERROR) << "couldn't convert CryptoOperation::dataInput";
+ return convertStatus(status);
+ }
+ break;
+ case ndk_hwcrypto::CryptoOperation::dataOutput:
+ cppOperationData = convertOperationData(
+ operation.get<ndk_hwcrypto::CryptoOperation::dataOutput>());
+ if (cppOperationData.has_value()) {
+ cppOperation.set<cpp_hwcrypto::CryptoOperation::dataOutput>(
+ std::move(cppOperationData.value()));
+ } else {
+ LOG(ERROR) << "couldn't convert CryptoOperation::dataOutput";
+ return convertStatus(status);
+ }
+ break;
+ case ndk_hwcrypto::CryptoOperation::destroyContext:
+ cppOperation.set<cpp_hwcrypto::CryptoOperation::destroyContext>(
+ std::move(voidObj));
+ break;
+ case ndk_hwcrypto::CryptoOperation::finish:
+ cppOperation.set<cpp_hwcrypto::CryptoOperation::finish>(std::move(voidObj));
+ break;
+ default:
+ // This shouldn't happen
+ LOG(ERROR) << "received unknown crypto operation";
+ return convertStatus(status);
+ }
+ cppSingleOperation.operations.push_back(std::move(cppOperation));
+ }
+ cppOperationSets.push_back(std::move(cppSingleOperation));
+ }
+ status = mHwCryptoOperations->processCommandList(&cppOperationSets, &binderResult);
+ if (status.isOk()) {
+ *aidl_return = std::vector<ndk_hwcrypto::CryptoOperationResult>();
+ for (cpp_hwcrypto::CryptoOperationResult& result : binderResult) {
+ ndk_hwcrypto::CryptoOperationResult ndkResult =
+ ndk_hwcrypto::CryptoOperationResult();
+ if (result.context != nullptr) {
+ insertBinderMapping<cpp_hwcrypto::ICryptoOperationContext,
+ ndk_hwcrypto::ICryptoOperationContext,
+ HwCryptoOperationContextNdk, contextMapping>(
+ result.context, &ndkResult.context);
+ } else {
+ ndkResult.context = nullptr;
+ }
+ aidl_return->push_back(std::move(ndkResult));
+ }
+ } else {
+ // No reason to copy back the data output vectors if this failed
+ LOG(ERROR) << "couldn't process command list";
+ return convertStatus(status);
+ }
+ // We need to copy the vectors from the cpp operations back to the ndk one
+ if (cppOperationSets.size() != operationSets->size()) {
+ LOG(ERROR) << "ndk and cpp operation sets had a different number of elements";
+ return convertStatus(Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT));
+ }
+ for (unsigned setIdx = 0; setIdx < cppOperationSets.size(); ++setIdx) {
+ if (cppOperationSets[setIdx].operations.size() !=
+ (*operationSets)[setIdx].operations.size()) {
+ LOG(ERROR) << "ndk and cpp operations on set " << setIdx
+ << " had a different number of elements";
+ return convertStatus(Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT));
+ }
+ for (unsigned operationIdx = 0;
+ operationIdx < cppOperationSets[setIdx].operations.size(); ++operationIdx) {
+ if (cppOperationSets[setIdx].operations[operationIdx].getTag() ==
+ cpp_hwcrypto::CryptoOperation::dataOutput) {
+ if ((*operationSets)[setIdx].operations[operationIdx].getTag() !=
+ ndk_hwcrypto::CryptoOperation::dataOutput) {
+ LOG(ERROR)
+ << "ndk and cpp operations on set " << setIdx << " and operation "
+ << operationIdx << " had a different operation type";
+ return convertStatus(
+ Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT));
+ }
+ if (cppOperationSets[setIdx]
+ .operations[operationIdx]
+ .get<cpp_hwcrypto::CryptoOperation::dataOutput>()
+ .getTag() == cpp_hwcrypto::types::OperationData::dataBuffer) {
+ // This is the only case on which we need to move the data backto the
+ // original array
+ if ((*operationSets)[setIdx]
+ .operations[operationIdx]
+ .get<ndk_hwcrypto::CryptoOperation::dataOutput>()
+ .getTag() != ndk_hwcrypto::types::OperationData::dataBuffer) {
+ LOG(ERROR) << "ndk and cpp operations on set " << setIdx
+ << " and operation " << operationIdx
+ << " had a different operation data output type";
+ return convertStatus(
+ Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT));
+ }
+ (*operationSets)[setIdx]
+ .operations[operationIdx]
+ .get<ndk_hwcrypto::CryptoOperation::dataOutput>()
+ .set<ndk_hwcrypto::types::OperationData::dataBuffer>(
+ cppOperationSets[setIdx]
+ .operations[operationIdx]
+ .get<cpp_hwcrypto::CryptoOperation::dataOutput>()
+ .get<cpp_hwcrypto::types::OperationData::
+ dataBuffer>());
+ }
+ }
+ }
+ }
+ return convertStatus(status);
}
};
class OpaqueKeyNdk : public ndk_hwcrypto::BnOpaqueKey {
private:
sp<cpp_hwcrypto::IOpaqueKey> mOpaqueKey;
+ std::weak_ptr<ndk_hwcrypto::IOpaqueKey> self;
public:
OpaqueKeyNdk(sp<cpp_hwcrypto::IOpaqueKey> opaqueKey) : mOpaqueKey(std::move(opaqueKey)) {}
+ ~OpaqueKeyNdk() { keyMapping.erase(self); }
+
static std::shared_ptr<OpaqueKeyNdk> Create(sp<cpp_hwcrypto::IOpaqueKey> opaqueKey) {
if (opaqueKey == nullptr) {
return nullptr;
@@ -213,6 +614,7 @@
LOG(ERROR) << "failed to allocate HwCryptoKey";
return nullptr;
}
+ opaqueKeyNdk->self = opaqueKeyNdk;
return opaqueKeyNdk;
}