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