1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //! Implementation of the `IHwCryptoOperations` AIDL interface. It can be use to retrieve the 18 //! key generation interface and to process cryptographic operations. 19 20 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{ 21 CryptoOperationResult::CryptoOperationResult, CryptoOperationSet::CryptoOperationSet, 22 IHwCryptoOperations::BnHwCryptoOperations, IHwCryptoOperations::IHwCryptoOperations, 23 }; 24 use android_hardware_security_see_hwcrypto::binder; 25 use hwcryptohal_common::hwcrypto_err; 26 27 use crate::cmd_processing::CmdProcessorContext; 28 use crate::crypto_operation_context::{BinderCryptoOperationContext, CryptoOperationContext}; 29 30 /// The `IHwCryptoOperations` implementation. 31 pub struct HwCryptoOperations; 32 33 impl binder::Interface for HwCryptoOperations {} 34 35 impl HwCryptoOperations { new_binder() -> binder::Strong<dyn IHwCryptoOperations>36 pub(crate) fn new_binder() -> binder::Strong<dyn IHwCryptoOperations> { 37 let hwcrypto_operations = HwCryptoOperations; 38 BnHwCryptoOperations::new_binder(hwcrypto_operations, binder::BinderFeatures::default()) 39 } 40 } 41 42 impl IHwCryptoOperations for HwCryptoOperations { processCommandList( &self, command_lists: &mut std::vec::Vec<CryptoOperationSet>, ) -> binder::Result<Vec<CryptoOperationResult>>43 fn processCommandList( 44 &self, 45 command_lists: &mut std::vec::Vec<CryptoOperationSet>, 46 ) -> binder::Result<Vec<CryptoOperationResult>> { 47 let mut results = Vec::<CryptoOperationResult>::new(); 48 for command_list in command_lists { 49 results.try_reserve(1).map_err(|e| { 50 hwcrypto_err!(ALLOCATION_ERROR, "couldn't grow result vector: {:?}", e) 51 })?; 52 results.push(CryptoOperationResult { context: None }); 53 match &command_list.context { 54 None => { 55 let mut cmd_processor = CmdProcessorContext::new(); 56 cmd_processor.process_all_steps(&mut command_list.operations)?; 57 if !cmd_processor.is_destroyed() { 58 let operation_context = CryptoOperationContext::new_binder(cmd_processor); 59 (*results 60 .last_mut() 61 .expect("shouldn't happen, we pushed an element before match")) 62 .context = Some(operation_context); 63 } 64 } 65 Some(operation_context) => { 66 BinderCryptoOperationContext::from(operation_context.clone()) 67 .process_all_steps(&mut command_list.operations)?; 68 } 69 } 70 } 71 Ok(results) 72 } 73 } 74 75 #[cfg(test)] 76 mod tests { 77 use super::*; 78 use crate::hwcrypto_ipc_server::RUST_SERVICE_PORT; 79 use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::{ 80 types::{ 81 AesCipherMode::AesCipherMode, CipherModeParameters::CipherModeParameters, 82 HmacOperationParameters::HmacOperationParameters, KeyLifetime::KeyLifetime, 83 KeyType::KeyType, KeyUse::KeyUse, OperationData::OperationData, 84 SymmetricCryptoParameters::SymmetricCryptoParameters, 85 SymmetricOperation::SymmetricOperation, 86 SymmetricOperationParameters::SymmetricOperationParameters, 87 }, 88 CryptoOperation::CryptoOperation, 89 IHwCryptoKey::{ 90 DerivedKey::DerivedKey, DerivedKeyParameters::DerivedKeyParameters, 91 DerivedKeyPolicy::DerivedKeyPolicy, DeviceKeyId::DeviceKeyId, 92 DiceBoundDerivationKey::DiceBoundDerivationKey, 93 DiceCurrentBoundKeyResult::DiceCurrentBoundKeyResult, IHwCryptoKey, KeySlot::KeySlot, 94 }, 95 KeyPolicy::KeyPolicy, 96 OperationParameters::OperationParameters, 97 }; 98 use binder::Strong; 99 use rpcbinder::RpcSession; 100 use test::{assert_ok, expect, expect_eq}; 101 102 #[test] aes_simple_test_from_binder()103 fn aes_simple_test_from_binder() { 104 let hw_device_key: Strong<dyn IHwCryptoKey> = 105 RpcSession::new().setup_trusty_client(RUST_SERVICE_PORT).expect("Failed to connect"); 106 let derivation_key = DiceBoundDerivationKey::KeyId(DeviceKeyId::DEVICE_BOUND_KEY); 107 let key_and_policy = 108 assert_ok!(hw_device_key.deriveCurrentDicePolicyBoundKey(&derivation_key)); 109 let DiceCurrentBoundKeyResult { diceBoundKey: key, dicePolicyForKeyVersion: policy } = 110 key_and_policy; 111 expect!(key.is_some(), "should have received a key"); 112 expect!(policy.len() > 0, "should have received a DICE policy"); 113 114 let hw_crypto = hw_device_key.getHwCryptoOperations().expect("Failed to get crypto ops."); 115 let usage = KeyUse::ENCRYPT_DECRYPT; 116 let key_type = KeyType::AES_256_CBC_PKCS7_PADDING; 117 let policy = KeyPolicy { 118 usage, 119 keyLifetime: KeyLifetime::HARDWARE, 120 keyPermissions: Vec::new(), 121 keyType: key_type, 122 keyManagementKey: false, 123 }; 124 125 let cbor_policy = hwcryptohal_common::policy::cbor_serialize_key_policy(&policy) 126 .expect("couldn't serialize policy"); 127 let key_policy = DerivedKeyPolicy::OpaqueKey(cbor_policy); 128 let params = DerivedKeyParameters { 129 derivationKey: key, 130 keyPolicy: key_policy, 131 context: "context".as_bytes().to_vec(), 132 }; 133 let derived_key = assert_ok!(hw_device_key.deriveKey(¶ms)); 134 let key = match derived_key { 135 DerivedKey::Opaque(key) => key.expect("key shouldn't be NULL"), 136 DerivedKey::ExplicitKey(_) => panic!("wrong type of key received"), 137 }; 138 139 let nonce = [0u8; 16]; 140 let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters { 141 nonce: nonce.into(), 142 })); 143 let direction = SymmetricOperation::ENCRYPT; 144 let sym_op_params = 145 SymmetricOperationParameters { key: Some(key.clone()), direction, parameters }; 146 let op_params = OperationParameters::SymmetricCrypto(sym_op_params); 147 let mut cmd_list = Vec::<CryptoOperation>::new(); 148 let data_output = OperationData::DataBuffer(Vec::new()); 149 cmd_list.push(CryptoOperation::DataOutput(data_output)); 150 cmd_list.push(CryptoOperation::SetOperationParameters(op_params)); 151 let input_data = OperationData::DataBuffer("string to be encrypted".as_bytes().to_vec()); 152 cmd_list.push(CryptoOperation::DataInput(input_data)); 153 let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list }; 154 let mut crypto_sets = Vec::new(); 155 crypto_sets.push(crypto_op_set); 156 let mut op_result = 157 hw_crypto.processCommandList(&mut crypto_sets).expect("couldn't process commands"); 158 // Extracting the vector from the command list because of ownership 159 let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) = 160 crypto_sets.remove(0).operations.remove(0) 161 else { 162 panic!("not reachable, we created this object above on the test"); 163 }; 164 let context = op_result.remove(0).context; 165 // Separating the finish call on a different command set to test the returned context 166 let mut cmd_list = Vec::<CryptoOperation>::new(); 167 let data_output = OperationData::DataBuffer(encrypted_data); 168 cmd_list.push(CryptoOperation::DataOutput(data_output)); 169 cmd_list.push(CryptoOperation::Finish(None)); 170 let crypto_op_set = CryptoOperationSet { context, operations: cmd_list }; 171 let mut crypto_sets = Vec::new(); 172 crypto_sets.push(crypto_op_set); 173 hw_crypto.processCommandList(&mut crypto_sets).expect("couldn't process commands"); 174 let CryptoOperation::DataOutput(OperationData::DataBuffer(encrypted_data)) = 175 crypto_sets.remove(0).operations.remove(0) 176 else { 177 panic!("not reachable, we created this object above on the test"); 178 }; 179 180 //// Decrypting 181 let parameters = SymmetricCryptoParameters::Aes(AesCipherMode::Cbc(CipherModeParameters { 182 nonce: nonce.into(), 183 })); 184 let direction = SymmetricOperation::DECRYPT; 185 let sym_op_params = SymmetricOperationParameters { key: Some(key), direction, parameters }; 186 let op_params = OperationParameters::SymmetricCrypto(sym_op_params); 187 let mut cmd_list = Vec::<CryptoOperation>::new(); 188 let data_output = OperationData::DataBuffer(Vec::new()); 189 cmd_list.push(CryptoOperation::DataOutput(data_output)); 190 cmd_list.push(CryptoOperation::SetOperationParameters(op_params)); 191 cmd_list.push(CryptoOperation::DataInput(OperationData::DataBuffer(encrypted_data))); 192 cmd_list.push(CryptoOperation::Finish(None)); 193 let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list }; 194 let mut crypto_sets = Vec::new(); 195 crypto_sets.push(crypto_op_set); 196 hw_crypto.processCommandList(&mut crypto_sets).expect("couldn't process commands"); 197 // Extracting the vector from the command list because of ownership 198 let CryptoOperation::DataOutput(OperationData::DataBuffer(decrypted_data)) = 199 crypto_sets.remove(0).operations.remove(0) 200 else { 201 panic!("not reachable, we created this object above on the test"); 202 }; 203 let decrypted_msg = 204 String::from_utf8(decrypted_data).expect("couldn't decode received message"); 205 expect_eq!(decrypted_msg, "string to be encrypted", "couldn't retrieve original message"); 206 } 207 208 #[test] hmac_simple_test_from_binder()209 fn hmac_simple_test_from_binder() { 210 let hw_key: Strong<dyn IHwCryptoKey> = 211 RpcSession::new().setup_trusty_client(RUST_SERVICE_PORT).expect("Failed to connect"); 212 213 let key = 214 hw_key.getKeyslotData(KeySlot::KEYMINT_SHARED_HMAC_KEY).expect("couldn't get key"); 215 216 let hw_crypto = hw_key.getHwCryptoOperations().expect("Failed to get crypto ops."); 217 218 let hmac_parameters = HmacOperationParameters { key: Some(key.clone()) }; 219 let op_parameters = OperationParameters::Hmac(hmac_parameters); 220 let mut cmd_list = Vec::<CryptoOperation>::new(); 221 let data_output = OperationData::DataBuffer(Vec::new()); 222 cmd_list.push(CryptoOperation::DataOutput(data_output)); 223 cmd_list.push(CryptoOperation::SetOperationParameters(op_parameters)); 224 let input_data = OperationData::DataBuffer("text to be mac'ed".as_bytes().to_vec()); 225 cmd_list.push(CryptoOperation::DataInput(input_data)); 226 cmd_list.push(CryptoOperation::Finish(None)); 227 let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list }; 228 let mut crypto_sets = Vec::new(); 229 crypto_sets.push(crypto_op_set); 230 hw_crypto.processCommandList(&mut crypto_sets).expect("couldn't process commands"); 231 // Extracting the vector from the command list because of ownership 232 let CryptoOperation::DataOutput(OperationData::DataBuffer(mac)) = 233 crypto_sets.remove(0).operations.remove(0) 234 else { 235 panic!("not reachable, we created this object above on the test"); 236 }; 237 238 //Getting a second mac to compare 239 let hmac_parameters = HmacOperationParameters { key: Some(key) }; 240 let op_parameters = OperationParameters::Hmac(hmac_parameters); 241 let mut cmd_list = Vec::<CryptoOperation>::new(); 242 let data_output = OperationData::DataBuffer(Vec::new()); 243 cmd_list.push(CryptoOperation::DataOutput(data_output)); 244 cmd_list.push(CryptoOperation::SetOperationParameters(op_parameters)); 245 let input_data = OperationData::DataBuffer("text to be mac'ed".as_bytes().to_vec()); 246 cmd_list.push(CryptoOperation::DataInput(input_data)); 247 cmd_list.push(CryptoOperation::Finish(None)); 248 let crypto_op_set = CryptoOperationSet { context: None, operations: cmd_list }; 249 let mut crypto_sets = Vec::new(); 250 crypto_sets.push(crypto_op_set); 251 hw_crypto.processCommandList(&mut crypto_sets).expect("couldn't process commands"); 252 // Extracting the vector from the command list because of ownership 253 let CryptoOperation::DataOutput(OperationData::DataBuffer(mac2)) = 254 crypto_sets.remove(0).operations.remove(0) 255 else { 256 panic!("not reachable, we created this object above on the test"); 257 }; 258 expect_eq!(mac, mac2, "got a different mac"); 259 } 260 } 261