xref: /aosp_15_r20/system/security/keystore2/tests/keystore2_client_test_utils.rs (revision e1997b9af69e3155ead6e072d106a0077849ffba)
1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
16     BlockMode::BlockMode, Digest::Digest, ErrorCode::ErrorCode,
17     KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
18     Tag::Tag,
19 };
20 use android_system_keystore2::aidl::android::system::keystore2::{
21     CreateOperationResponse::CreateOperationResponse, Domain::Domain,
22     IKeystoreOperation::IKeystoreOperation, IKeystoreSecurityLevel::IKeystoreSecurityLevel,
23     IKeystoreService::IKeystoreService, KeyDescriptor::KeyDescriptor, KeyMetadata::KeyMetadata,
24     KeyParameters::KeyParameters, ResponseCode::ResponseCode,
25 };
26 use binder::wait_for_interface;
27 use keystore2_test_utils::{
28     authorizations, key_generations,
29     key_generations::Error,
30     run_as,
31     run_as::{ChannelReader, ChannelWriter},
32     SecLevel,
33 };
34 use nix::unistd::{Gid, Uid};
35 use openssl::bn::BigNum;
36 use openssl::encrypt::Encrypter;
37 use openssl::error::ErrorStack;
38 use openssl::hash::MessageDigest;
39 use openssl::nid::Nid;
40 use openssl::pkey::PKey;
41 use openssl::pkey::Public;
42 use openssl::rsa::Padding;
43 use openssl::sign::Verifier;
44 use openssl::x509::X509;
45 use packagemanager_aidl::aidl::android::content::pm::IPackageManagerNative::IPackageManagerNative;
46 use serde::{Deserialize, Serialize};
47 use std::process::{Command, Output};
48 
49 /// This enum is used to communicate between parent and child processes.
50 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
51 pub enum TestOutcome {
52     Ok,
53     BackendBusy,
54     InvalidHandle,
55     OtherErr,
56 }
57 
58 /// This is used to notify the child or parent process that the expected state is reached.
59 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
60 pub struct BarrierReached;
61 
62 /// This is used to notify the child or parent process that the expected state is reached,
63 /// passing a value
64 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
65 pub struct BarrierReachedWithData<T: Send + Sync>(pub T);
66 
67 impl<T: Send + Sync> BarrierReachedWithData<T> {
new(val: T) -> Self68     pub fn new(val: T) -> Self {
69         Self(val)
70     }
71 }
72 
73 /// Forced operation.
74 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
75 pub struct ForcedOp(pub bool);
76 
77 /// Sample plain text input for encrypt operation.
78 pub const SAMPLE_PLAIN_TEXT: &[u8] = b"my message 11111";
79 
80 pub const PACKAGE_MANAGER_NATIVE_SERVICE: &str = "package_native";
81 const APP_ATTEST_KEY_FEATURE: &str = "android.hardware.keystore.app_attest_key";
82 const DEVICE_ID_ATTESTATION_FEATURE: &str = "android.software.device_id_attestation";
83 const STRONGBOX_KEYSTORE_FEATURE: &str = "android.hardware.strongbox_keystore";
84 
85 /// Determines whether app_attest_key_feature is supported or not.
app_attest_key_feature_exists() -> bool86 pub fn app_attest_key_feature_exists() -> bool {
87     let pm = wait_for_interface::<dyn IPackageManagerNative>(PACKAGE_MANAGER_NATIVE_SERVICE)
88         .expect("Failed to get package manager native service.");
89 
90     pm.hasSystemFeature(APP_ATTEST_KEY_FEATURE, 0).expect("hasSystemFeature failed.")
91 }
92 
93 /// Determines whether device_id_attestation is supported or not.
device_id_attestation_feature_exists() -> bool94 pub fn device_id_attestation_feature_exists() -> bool {
95     let pm = wait_for_interface::<dyn IPackageManagerNative>(PACKAGE_MANAGER_NATIVE_SERVICE)
96         .expect("Failed to get package manager native service.");
97 
98     pm.hasSystemFeature(DEVICE_ID_ATTESTATION_FEATURE, 0).expect("hasSystemFeature failed.")
99 }
100 
101 /// Determines whether device-unique attestation might be supported by StrongBox.
skip_device_unique_attestation_tests() -> bool102 pub fn skip_device_unique_attestation_tests() -> bool {
103     let pm = wait_for_interface::<dyn IPackageManagerNative>(PACKAGE_MANAGER_NATIVE_SERVICE)
104         .expect("Failed to get package manager native service.");
105 
106     // Device unique attestation was first included in Keymaster 4.1.
107     !pm.hasSystemFeature(STRONGBOX_KEYSTORE_FEATURE, 41).expect("hasSystemFeature failed.")
108 }
109 
110 /// Determines whether to skip device id attestation tests on GSI build with API level < 34.
skip_device_id_attest_tests() -> bool111 pub fn skip_device_id_attest_tests() -> bool {
112     // b/298586194, there are some devices launched with Android T, and they will be receiving
113     // only system update and not vendor update, newly added attestation properties
114     // (ro.product.*_for_attestation) reading logic would not be available for such devices
115     // hence skipping this test for such scenario.
116 
117     get_vsr_api_level() < 34 && key_generations::is_gsi()
118 }
119 
120 #[macro_export]
121 macro_rules! skip_test_if_no_app_attest_key_feature {
122     () => {
123         if !app_attest_key_feature_exists() {
124             return;
125         }
126     };
127 }
128 
129 #[macro_export]
130 macro_rules! skip_test_if_no_device_id_attestation_feature {
131     () => {
132         if !device_id_attestation_feature_exists() {
133             return;
134         }
135     };
136 }
137 
138 #[macro_export]
139 macro_rules! skip_device_id_attestation_tests {
140     () => {
141         if skip_device_id_attest_tests() {
142             return;
143         }
144     };
145 }
146 
147 #[macro_export]
148 macro_rules! require_keymint {
149     ($sl:ident) => {
150         if !$sl.is_keymint() {
151             return;
152         }
153     };
154 }
155 
156 /// Generate EC key and grant it to the list of users with given access vector.
157 /// Returns the list of granted keys `nspace` values in the order of given grantee uids.
generate_ec_key_and_grant_to_users( sl: &SecLevel, alias: Option<String>, grantee_uids: Vec<i32>, access_vector: i32, ) -> Result<Vec<i64>, binder::Status>158 pub fn generate_ec_key_and_grant_to_users(
159     sl: &SecLevel,
160     alias: Option<String>,
161     grantee_uids: Vec<i32>,
162     access_vector: i32,
163 ) -> Result<Vec<i64>, binder::Status> {
164     let key_metadata =
165         key_generations::generate_ec_p256_signing_key(sl, Domain::APP, -1, alias, None)?;
166 
167     let mut granted_keys = Vec::new();
168 
169     for uid in grantee_uids {
170         let granted_key = sl.keystore2.grant(&key_metadata.key, uid, access_vector)?;
171         assert_eq!(granted_key.domain, Domain::GRANT);
172         granted_keys.push(granted_key.nspace);
173     }
174 
175     Ok(granted_keys)
176 }
177 
178 /// Generate a EC_P256 key using given domain, namespace and alias.
179 /// Create an operation using the generated key and perform sample signing operation.
create_signing_operation( forced_op: ForcedOp, op_purpose: KeyPurpose, op_digest: Digest, domain: Domain, nspace: i64, alias: Option<String>, ) -> binder::Result<CreateOperationResponse>180 pub fn create_signing_operation(
181     forced_op: ForcedOp,
182     op_purpose: KeyPurpose,
183     op_digest: Digest,
184     domain: Domain,
185     nspace: i64,
186     alias: Option<String>,
187 ) -> binder::Result<CreateOperationResponse> {
188     let sl = SecLevel::tee();
189 
190     let key_metadata =
191         key_generations::generate_ec_p256_signing_key(&sl, domain, nspace, alias, None).unwrap();
192 
193     sl.binder.createOperation(
194         &key_metadata.key,
195         &authorizations::AuthSetBuilder::new().purpose(op_purpose).digest(op_digest),
196         forced_op.0,
197     )
198 }
199 
200 /// Performs sample signing operation.
perform_sample_sign_operation( op: &binder::Strong<dyn IKeystoreOperation>, ) -> Result<(), binder::Status>201 pub fn perform_sample_sign_operation(
202     op: &binder::Strong<dyn IKeystoreOperation>,
203 ) -> Result<(), binder::Status> {
204     op.update(b"my message")?;
205     let sig = op.finish(None, None)?;
206     assert!(sig.is_some());
207     Ok(())
208 }
209 
210 /// Perform sample HMAC sign and verify operations.
perform_sample_hmac_sign_verify_op( sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, key: &KeyDescriptor, )211 pub fn perform_sample_hmac_sign_verify_op(
212     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
213     key: &KeyDescriptor,
214 ) {
215     let sign_op = sec_level
216         .createOperation(
217             key,
218             &authorizations::AuthSetBuilder::new()
219                 .purpose(KeyPurpose::SIGN)
220                 .digest(Digest::SHA_2_256)
221                 .mac_length(256),
222             false,
223         )
224         .unwrap();
225     assert!(sign_op.iOperation.is_some());
226 
227     let op = sign_op.iOperation.unwrap();
228     op.update(b"my message").unwrap();
229     let sig = op.finish(None, None).unwrap();
230     assert!(sig.is_some());
231 
232     let sig = sig.unwrap();
233     let verify_op = sec_level
234         .createOperation(
235             key,
236             &authorizations::AuthSetBuilder::new()
237                 .purpose(KeyPurpose::VERIFY)
238                 .digest(Digest::SHA_2_256),
239             false,
240         )
241         .unwrap();
242     assert!(verify_op.iOperation.is_some());
243 
244     let op = verify_op.iOperation.unwrap();
245     let result = op.finish(Some(b"my message"), Some(&sig)).unwrap();
246     assert!(result.is_none());
247 }
248 
249 /// Map KeyMint Digest values to OpenSSL MessageDigest.
get_openssl_digest_mode(digest: Option<Digest>) -> MessageDigest250 pub fn get_openssl_digest_mode(digest: Option<Digest>) -> MessageDigest {
251     match digest {
252         Some(Digest::MD5) => MessageDigest::md5(),
253         Some(Digest::SHA1) => MessageDigest::sha1(),
254         Some(Digest::SHA_2_224) => MessageDigest::sha224(),
255         Some(Digest::SHA_2_256) => MessageDigest::sha256(),
256         Some(Digest::SHA_2_384) => MessageDigest::sha384(),
257         Some(Digest::SHA_2_512) => MessageDigest::sha512(),
258         _ => MessageDigest::sha256(),
259     }
260 }
261 
262 /// Map KeyMint PaddingMode values to OpenSSL Padding.
get_openssl_padding_mode(padding: PaddingMode) -> Padding263 pub fn get_openssl_padding_mode(padding: PaddingMode) -> Padding {
264     match padding {
265         PaddingMode::RSA_OAEP => Padding::PKCS1_OAEP,
266         PaddingMode::RSA_PSS => Padding::PKCS1_PSS,
267         PaddingMode::RSA_PKCS1_1_5_SIGN => Padding::PKCS1,
268         PaddingMode::RSA_PKCS1_1_5_ENCRYPT => Padding::PKCS1,
269         _ => Padding::NONE,
270     }
271 }
272 
273 /// Perform sample sign and verify operations using RSA or EC key.
perform_sample_asym_sign_verify_op( sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, key_metadata: &KeyMetadata, padding: Option<PaddingMode>, digest: Option<Digest>, )274 pub fn perform_sample_asym_sign_verify_op(
275     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
276     key_metadata: &KeyMetadata,
277     padding: Option<PaddingMode>,
278     digest: Option<Digest>,
279 ) {
280     let mut authorizations = authorizations::AuthSetBuilder::new().purpose(KeyPurpose::SIGN);
281     if let Some(value) = padding {
282         authorizations = authorizations.padding_mode(value);
283     }
284     if let Some(value) = digest {
285         authorizations = authorizations.digest(value);
286     }
287 
288     let sign_op = sec_level.createOperation(&key_metadata.key, &authorizations, false).unwrap();
289     assert!(sign_op.iOperation.is_some());
290 
291     let op = sign_op.iOperation.unwrap();
292     op.update(b"my message").unwrap();
293     let sig = op.finish(None, None).unwrap();
294     assert!(sig.is_some());
295 
296     let sig = sig.unwrap();
297     let cert_bytes = key_metadata.certificate.as_ref().unwrap();
298     let cert = X509::from_der(cert_bytes.as_ref()).unwrap();
299     let pub_key = cert.public_key().unwrap();
300     let mut verifier = Verifier::new(get_openssl_digest_mode(digest), pub_key.as_ref()).unwrap();
301     if let Some(value) = padding {
302         verifier.set_rsa_padding(get_openssl_padding_mode(value)).unwrap();
303     }
304     verifier.update(b"my message").unwrap();
305     assert!(verifier.verify(&sig).unwrap());
306 }
307 
308 /// Create new operation on child proc and perform simple operation after parent notification.
309 ///
310 /// # Safety
311 ///
312 /// Must only be called from a single-threaded process (e.g. as enforced by `AndroidTest.xml`
313 /// setting `--test-threads=1`).
execute_op_run_as_child( target_ctx: &'static str, domain: Domain, nspace: i64, alias: Option<String>, auid: Uid, agid: Gid, forced_op: ForcedOp, ) -> run_as::ChildHandle<TestOutcome, BarrierReached>314 pub unsafe fn execute_op_run_as_child(
315     target_ctx: &'static str,
316     domain: Domain,
317     nspace: i64,
318     alias: Option<String>,
319     auid: Uid,
320     agid: Gid,
321     forced_op: ForcedOp,
322 ) -> run_as::ChildHandle<TestOutcome, BarrierReached> {
323     let child_fn = move |reader: &mut ChannelReader<BarrierReached>,
324                          writer: &mut ChannelWriter<BarrierReached>| {
325         let result = key_generations::map_ks_error(create_signing_operation(
326             forced_op,
327             KeyPurpose::SIGN,
328             Digest::SHA_2_256,
329             domain,
330             nspace,
331             alias,
332         ));
333 
334         // Let the parent know that an operation has been started, then
335         // wait until the parent notifies us to continue, so the operation
336         // remains open.
337         writer.send(&BarrierReached {});
338         reader.recv();
339 
340         // Continue performing the operation after parent notifies.
341         match &result {
342             Ok(CreateOperationResponse { iOperation: Some(op), .. }) => {
343                 match key_generations::map_ks_error(perform_sample_sign_operation(op)) {
344                     Ok(()) => TestOutcome::Ok,
345                     Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)) => {
346                         TestOutcome::InvalidHandle
347                     }
348                     Err(e) => panic!("Error in performing op: {:#?}", e),
349                 }
350             }
351             Ok(_) => TestOutcome::OtherErr,
352             Err(Error::Rc(ResponseCode::BACKEND_BUSY)) => TestOutcome::BackendBusy,
353             _ => TestOutcome::OtherErr,
354         }
355     };
356 
357     // Safety: The caller guarantees that there are no other threads.
358     unsafe {
359         run_as::run_as_child(target_ctx, auid, agid, child_fn)
360             .expect("Failed to create an operation.")
361     }
362 }
363 
364 /// Get NONCE value from given key parameters list.
get_op_nonce(parameters: &KeyParameters) -> Option<Vec<u8>>365 pub fn get_op_nonce(parameters: &KeyParameters) -> Option<Vec<u8>> {
366     for key_param in &parameters.keyParameter {
367         if key_param.tag == Tag::NONCE {
368             if let KeyParameterValue::Blob(val) = &key_param.value {
369                 return Some(val.clone());
370             }
371         }
372     }
373     None
374 }
375 
376 /// This performs sample encryption operation with given symmetric key (AES/3DES).
377 /// It encrypts `SAMPLE_PLAIN_TEXT` of length 128-bits.
perform_sample_sym_key_encrypt_op( sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, padding_mode: PaddingMode, block_mode: BlockMode, nonce: &mut Option<Vec<u8>>, mac_len: Option<i32>, key: &KeyDescriptor, ) -> binder::Result<Option<Vec<u8>>>378 pub fn perform_sample_sym_key_encrypt_op(
379     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
380     padding_mode: PaddingMode,
381     block_mode: BlockMode,
382     nonce: &mut Option<Vec<u8>>,
383     mac_len: Option<i32>,
384     key: &KeyDescriptor,
385 ) -> binder::Result<Option<Vec<u8>>> {
386     let mut op_params = authorizations::AuthSetBuilder::new()
387         .purpose(KeyPurpose::ENCRYPT)
388         .padding_mode(padding_mode)
389         .block_mode(block_mode);
390     if let Some(value) = nonce {
391         op_params = op_params.nonce(value.to_vec());
392     }
393 
394     if let Some(val) = mac_len {
395         op_params = op_params.mac_length(val);
396     }
397 
398     let op_response = sec_level.createOperation(key, &op_params, false)?;
399     assert!(op_response.iOperation.is_some());
400     let op = op_response.iOperation.unwrap();
401     if op_response.parameters.is_some() && nonce.is_none() {
402         *nonce = get_op_nonce(&op_response.parameters.unwrap());
403     }
404     op.finish(Some(SAMPLE_PLAIN_TEXT), None)
405 }
406 
407 /// This performs sample decryption operation with given symmetric key (AES/3DES).
perform_sample_sym_key_decrypt_op( sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, input: &[u8], padding_mode: PaddingMode, block_mode: BlockMode, nonce: &mut Option<Vec<u8>>, mac_len: Option<i32>, key: &KeyDescriptor, ) -> binder::Result<Option<Vec<u8>>>408 pub fn perform_sample_sym_key_decrypt_op(
409     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
410     input: &[u8],
411     padding_mode: PaddingMode,
412     block_mode: BlockMode,
413     nonce: &mut Option<Vec<u8>>,
414     mac_len: Option<i32>,
415     key: &KeyDescriptor,
416 ) -> binder::Result<Option<Vec<u8>>> {
417     let mut op_params = authorizations::AuthSetBuilder::new()
418         .purpose(KeyPurpose::DECRYPT)
419         .padding_mode(padding_mode)
420         .block_mode(block_mode);
421     if let Some(value) = nonce {
422         op_params = op_params.nonce(value.to_vec());
423     }
424 
425     if let Some(val) = mac_len {
426         op_params = op_params.mac_length(val);
427     }
428 
429     let op_response = sec_level.createOperation(key, &op_params, false)?;
430     assert!(op_response.iOperation.is_some());
431     let op = op_response.iOperation.unwrap();
432     op.finish(Some(input), None)
433 }
434 
435 /// Delete a key with domain APP.
delete_app_key( keystore2: &binder::Strong<dyn IKeystoreService>, alias: &str, ) -> binder::Result<()>436 pub fn delete_app_key(
437     keystore2: &binder::Strong<dyn IKeystoreService>,
438     alias: &str,
439 ) -> binder::Result<()> {
440     keystore2.deleteKey(&KeyDescriptor {
441         domain: Domain::APP,
442         nspace: -1,
443         alias: Some(alias.to_string()),
444         blob: None,
445     })
446 }
447 
448 /// Deletes all entries from keystore.
delete_all_entries(keystore2: &binder::Strong<dyn IKeystoreService>)449 pub fn delete_all_entries(keystore2: &binder::Strong<dyn IKeystoreService>) {
450     while keystore2.getNumberOfEntries(Domain::APP, -1).unwrap() != 0 {
451         let key_descriptors = keystore2.listEntries(Domain::APP, -1).unwrap();
452         key_descriptors.into_iter().map(|key| key.alias.unwrap()).for_each(|alias| {
453             delete_app_key(keystore2, &alias).unwrap();
454         });
455     }
456     assert!(keystore2.getNumberOfEntries(Domain::APP, -1).unwrap() == 0);
457 }
458 
459 /// Encrypt the secure key with given transport key.
encrypt_secure_key( sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>, secure_key: &[u8], aad: &[u8], nonce: Vec<u8>, mac_len: i32, key: &KeyDescriptor, ) -> binder::Result<Option<Vec<u8>>>460 pub fn encrypt_secure_key(
461     sec_level: &binder::Strong<dyn IKeystoreSecurityLevel>,
462     secure_key: &[u8],
463     aad: &[u8],
464     nonce: Vec<u8>,
465     mac_len: i32,
466     key: &KeyDescriptor,
467 ) -> binder::Result<Option<Vec<u8>>> {
468     let op_params = authorizations::AuthSetBuilder::new()
469         .purpose(KeyPurpose::ENCRYPT)
470         .padding_mode(PaddingMode::NONE)
471         .block_mode(BlockMode::GCM)
472         .nonce(nonce)
473         .mac_length(mac_len);
474 
475     let op_response = sec_level.createOperation(key, &op_params, false)?;
476 
477     let op = op_response.iOperation.unwrap();
478     op.updateAad(aad)?;
479     op.finish(Some(secure_key), None)
480 }
481 
482 /// Encrypt the transport key with given RSA wrapping key.
encrypt_transport_key( transport_key: &[u8], pkey: &PKey<Public>, ) -> Result<Vec<u8>, ErrorStack>483 pub fn encrypt_transport_key(
484     transport_key: &[u8],
485     pkey: &PKey<Public>,
486 ) -> Result<Vec<u8>, ErrorStack> {
487     let mut encrypter = Encrypter::new(pkey).unwrap();
488     encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
489     encrypter.set_rsa_oaep_md(MessageDigest::sha256()).unwrap();
490     encrypter.set_rsa_mgf1_md(MessageDigest::sha1()).unwrap();
491 
492     let input = transport_key.to_vec();
493     let buffer_len = encrypter.encrypt_len(&input).unwrap();
494     let mut encoded = vec![0u8; buffer_len];
495     let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
496     let encoded = &encoded[..encoded_len];
497 
498     Ok(encoded.to_vec())
499 }
500 
501 /// List aliases using given `startingPastAlias` and verify that the fetched list is matching with
502 /// the expected list of aliases.
verify_aliases( keystore2: &binder::Strong<dyn IKeystoreService>, starting_past_alias: Option<&str>, expected_aliases: Vec<String>, )503 pub fn verify_aliases(
504     keystore2: &binder::Strong<dyn IKeystoreService>,
505     starting_past_alias: Option<&str>,
506     expected_aliases: Vec<String>,
507 ) {
508     let key_descriptors =
509         keystore2.listEntriesBatched(Domain::APP, -1, starting_past_alias).unwrap();
510 
511     assert_eq!(key_descriptors.len(), expected_aliases.len());
512     assert!(key_descriptors
513         .iter()
514         .all(|key| expected_aliases.contains(key.alias.as_ref().unwrap())));
515 }
516 
517 // Get the value of the given system property, if the given system property doesn't exist
518 // then returns an empty byte vector.
get_system_prop(name: &str) -> Vec<u8>519 pub fn get_system_prop(name: &str) -> Vec<u8> {
520     match rustutils::system_properties::read(name) {
521         Ok(Some(value)) => {
522             return value.as_bytes().to_vec();
523         }
524         _ => {
525             vec![]
526         }
527     }
528 }
529 
get_integer_system_prop(name: &str) -> Option<i32>530 fn get_integer_system_prop(name: &str) -> Option<i32> {
531     let val = get_system_prop(name);
532     if val.is_empty() {
533         return None;
534     }
535     let val = std::str::from_utf8(&val).ok()?;
536     val.parse::<i32>().ok()
537 }
538 
get_vsr_api_level() -> i32539 pub fn get_vsr_api_level() -> i32 {
540     if let Some(api_level) = get_integer_system_prop("ro.vendor.api_level") {
541         return api_level;
542     }
543 
544     let vendor_api_level = get_integer_system_prop("ro.board.api_level")
545         .or_else(|| get_integer_system_prop("ro.board.first_api_level"));
546     let product_api_level = get_integer_system_prop("ro.product.first_api_level")
547         .or_else(|| get_integer_system_prop("ro.build.version.sdk"));
548 
549     match (vendor_api_level, product_api_level) {
550         (Some(v), Some(p)) => std::cmp::min(v, p),
551         (Some(v), None) => v,
552         (None, Some(p)) => p,
553         _ => panic!("Could not determine VSR API level"),
554     }
555 }
556 
557 /// Determines whether the SECOND-IMEI can be used as device attest-id.
is_second_imei_id_attestation_required( keystore2: &binder::Strong<dyn IKeystoreService>, ) -> bool558 pub fn is_second_imei_id_attestation_required(
559     keystore2: &binder::Strong<dyn IKeystoreService>,
560 ) -> bool {
561     keystore2.getInterfaceVersion().unwrap() >= 3 && get_vsr_api_level() > 33
562 }
563 
564 /// Run a service command and collect the output.
run_service_command(command: &[&str]) -> std::io::Result<Output>565 pub fn run_service_command(command: &[&str]) -> std::io::Result<Output> {
566     Command::new("cmd").args(command).output()
567 }
568 
569 /// Get IMEI from telephony service.
get_imei(slot: i32) -> Option<Vec<u8>>570 pub fn get_imei(slot: i32) -> Option<Vec<u8>> {
571     let mut cmd = vec!["phone", "get-imei"];
572     let slot_str = slot.to_string();
573     cmd.push(slot_str.as_str());
574     let output = run_service_command(&cmd).unwrap();
575     if output.status.success() {
576         let stdout = String::from_utf8(output.stdout).unwrap();
577         let mut split_out = stdout.split_whitespace();
578         let imei = split_out.next_back().unwrap();
579         if imei == "null" {
580             return None;
581         }
582         return Some(imei.as_bytes().to_vec());
583     }
584 
585     None
586 }
587 
588 /// Get value of the given attestation id.
get_attest_id_value(attest_id: Tag, prop_name: &str) -> Option<Vec<u8>>589 pub fn get_attest_id_value(attest_id: Tag, prop_name: &str) -> Option<Vec<u8>> {
590     match attest_id {
591         Tag::ATTESTATION_ID_IMEI => get_imei(0),
592         Tag::ATTESTATION_ID_SECOND_IMEI => get_imei(1),
593         Tag::ATTESTATION_ID_SERIAL => Some(get_system_prop(format!("ro.{}", prop_name).as_str())),
594         _ => {
595             let prop_val =
596                 get_system_prop(format!("ro.product.{}_for_attestation", prop_name).as_str());
597             if !prop_val.is_empty() {
598                 Some(prop_val)
599             } else {
600                 let prop_val = get_system_prop(format!("ro.product.vendor.{}", prop_name).as_str());
601                 if !prop_val.is_empty() {
602                     Some(prop_val)
603                 } else {
604                     Some(get_system_prop(format!("ro.product.{}", prop_name).as_str()))
605                 }
606             }
607         }
608     }
609 }
610 
verify_certificate_subject_name(cert_bytes: &[u8], expected_subject: &[u8])611 pub fn verify_certificate_subject_name(cert_bytes: &[u8], expected_subject: &[u8]) {
612     let cert = X509::from_der(cert_bytes).unwrap();
613     let subject = cert.subject_name();
614     let cn = subject.entries_by_nid(Nid::COMMONNAME).next().unwrap();
615     assert_eq!(cn.data().as_slice(), expected_subject);
616 }
617 
verify_certificate_serial_num(cert_bytes: &[u8], expected_serial_num: &BigNum)618 pub fn verify_certificate_serial_num(cert_bytes: &[u8], expected_serial_num: &BigNum) {
619     let cert = X509::from_der(cert_bytes).unwrap();
620     let serial_num = cert.serial_number();
621     assert_eq!(serial_num.to_bn().as_ref().unwrap(), expected_serial_num);
622 }
623