1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      https://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.devicediagnostics
17 
18 import android.os.Bundle
19 import androidx.preference.Preference
20 import androidx.preference.PreferenceFragmentCompat
21 import com.google.android.attestation.AuthorizationList
22 import com.google.android.attestation.ParsedAttestationRecord
23 import com.google.android.attestation.RootOfTrust
24 import java.util.Optional
25 
26 class DisplayAttestationResultFragment(
27     private val record: ParsedAttestationRecord,
28     private val result: AttestationResult
29 ) : PreferenceFragmentCompat() {
onCreatePreferencesnull30     override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
31         setPreferencesFromResource(R.xml.attestation_details, rootKey)
32 
33         // By default, show a failure code for IMEI/Serial. It will get overridden if it's actually
34         // present.
35         if (
36             result == AttestationResult.VERIFIED || result == AttestationResult.SKIPPED_VERIFICATION
37         ) {
38             if (result == AttestationResult.VERIFIED) {
39                 show("attestation_verified", activity!!.resources.getString(R.string.yes))
40             } else {
41                 hide("attestation_verified")
42             }
43             show("attestation_imei", activity!!.resources.getString(R.string.unknown))
44             show("attestation_serial", activity!!.resources.getString(R.string.unknown))
45         } else {
46             show("attestation_verified", activity!!.resources.getString(R.string.no))
47             show("attestation_imei", activity!!.resources.getString(R.string.attestation_failed))
48             show("attestation_serial", activity!!.resources.getString(R.string.attestation_failed))
49         }
50 
51         if (isDeviceLocked()) {
52             show("attestation_device_locked", activity!!.resources.getString(R.string.yes))
53         } else {
54             show("attestation_device_locked", activity!!.resources.getString(R.string.no))
55         }
56 
57         show("attestation_verified_boot_state", activity!!.resources.getString(getVerifiedBootStateResId(record)))
58         show("attestation_security_level", record.attestationSecurityLevel.name)
59         show("attestation_keymaster_version", record.keymasterVersion.toString())
60         show("attestation_keymaster_security_level", record.keymasterSecurityLevel.name)
61         processAuthorizationList(record.softwareEnforced)
62         processAuthorizationList(record.teeEnforced)
63     }
64 
processAuthorizationListnull65     private fun processAuthorizationList(list: AuthorizationList) {
66         showInt("attestation_os_version", list.osVersion)
67         show("attestation_brand", list.attestationIdBrand)
68         show("attestation_device", list.attestationIdDevice)
69         show("attestation_product", list.attestationIdProduct)
70         show("attestation_serial", list.attestationIdSerial)
71         show("attestation_imei", list.attestationIdImei)
72         show("attestation_second_imei", list.attestationIdSecondImei)
73         show("attestation_meid", list.attestationIdMeid)
74         show("attestation_manufacturer", list.attestationIdManufacturer)
75         show("attestation_model", list.attestationIdModel)
76         showInt("attestation_vendor_patch_level", list.vendorPatchLevel)
77         showInt("attestation_boot_patch_level", list.bootPatchLevel)
78     }
79 
isDeviceLockednull80     private fun isDeviceLocked(): Boolean {
81         val root = record.teeEnforced.rootOfTrust
82         return root.isPresent && root.get().deviceLocked
83     }
84 
showIntnull85     private fun showInt(key: String, value: Optional<Int>?) {
86         if (value != null && value.isPresent) return show(key, value.get().toString())
87     }
88 
shownull89     private fun show(key: String, value: Optional<ByteArray>) {
90         if (value.isPresent) return show(key, value.get().toString(Charsets.UTF_8))
91     }
92 
shownull93     private fun show(key: String, text: String) {
94         val pref = findPreference<Preference>(key)!!
95         pref.summary = text
96         pref.isVisible = true
97     }
98 
hidenull99     private fun hide(key: String) {
100         findPreference<Preference>(key)!!.isVisible = false
101     }
102 }
getVerifiedBootStateResIdnull103 fun getVerifiedBootStateResId(record: ParsedAttestationRecord): Int {
104     val root = record.teeEnforced.rootOfTrust
105     if (
106         root.isPresent && root.get().verifiedBootState == RootOfTrust.VerifiedBootState.VERIFIED
107     ) {
108         return R.string.avb_verified
109     }
110     return R.string.avb_not_verified
111 }