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 ¶meters.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