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