1 /*
2  * Copyright (C) 2023 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  *      http://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.settings.biometrics2.ui.model
17 
18 import android.content.Intent.EXTRA_USER_ID
19 import android.os.Bundle
20 import android.os.UserHandle
21 import androidx.annotation.VisibleForTesting
22 import com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE
23 import com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN
24 import com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE
25 import java.time.Clock
26 
27 /**
28  * Secret credential data including
29  * 1. userId
30  * 2. challenge
31  * 3. token
32  * 4. gkPwHandle
33  */
34 class CredentialModel(bundle: Bundle?, private val clock: Clock) {
35 
36     private val mInitMillis = clock.millis()
37 
38     /** userId for this credential */
39     val userId: Int = (bundle ?: Bundle()).getInt(EXTRA_USER_ID, UserHandle.myUserId())
40 
41     private var clearGkPwHandleMillis: Long? = null
42 
43     /** Gatekeeper password handle */
44     var gkPwHandle: Long = (bundle ?: Bundle()).getLong(EXTRA_KEY_GK_PW_HANDLE, INVALID_GK_PW_HANDLE)
45         private set
46 
47     val isValidGkPwHandle: Boolean
48         get() = gkPwHandle != INVALID_GK_PW_HANDLE
49 
50     /** Clear gatekeeper password handle data */
clearGkPwHandlenull51     fun clearGkPwHandle() {
52         clearGkPwHandleMillis = clock.millis()
53         gkPwHandle = INVALID_GK_PW_HANDLE
54     }
55 
56     /** Check user id is valid or not */
57     val isValidUserId: Boolean
58         get() = userId != UserHandle.USER_NULL
59 
60     private var updateChallengeMillis: Long? = null
61 
62     var challenge: Long = (bundle ?: Bundle()).getLong(EXTRA_KEY_CHALLENGE, INVALID_CHALLENGE)
63         set(value) {
64             updateChallengeMillis = clock.millis()
65             field = value
66         }
67 
68     val isValidChallenge: Boolean
69         get() = challenge != INVALID_CHALLENGE
70 
71     private var updateTokenMillis: Long? = null
72 
73     /** Challenge token */
74     var token: ByteArray? = (bundle ?: Bundle()).getByteArray(EXTRA_KEY_CHALLENGE_TOKEN)
75         set(value) {
76             updateTokenMillis = clock.millis()
77             field = value
78         }
79 
80     val isValidToken: Boolean
81         get() = token != null
82 
83     /** Returns a string representation of the object */
toStringnull84     override fun toString(): String {
85         val gkPwHandleLen = "$gkPwHandle".length
86         val tokenLen = token?.size ?: 0
87         val challengeLen = "$challenge".length
88         return (javaClass.simpleName + ":{initMillis:$mInitMillis"
89                 + ", userId:$userId"
90                 + ", challenge:{len:$challengeLen"
91                 + ", updateMillis:$updateChallengeMillis}"
92                 + ", token:{len:$tokenLen, isValid:$isValidToken"
93                 + ", updateMillis:$updateTokenMillis}"
94                 + ", gkPwHandle:{len:$gkPwHandleLen, isValid:$isValidGkPwHandle"
95                 + ", clearMillis:$clearGkPwHandleMillis}"
96                 + " }")
97     }
98 
99     companion object {
100         /** Default value for an invalid challenge */
101         @VisibleForTesting
102         const val INVALID_CHALLENGE = -1L
103 
104         /** Default value if GkPwHandle is invalid */
105         @VisibleForTesting
106         const val INVALID_GK_PW_HANDLE = 0L
107     }
108 }
109