• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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 
17 package com.android.internal.widget;
18 
19 import android.annotation.IntDef;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.service.gatekeeper.GateKeeperResponse;
24 import android.util.Slog;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 
29 /**
30  * Response object for a ILockSettings credential verification request.
31  * @hide
32  */
33 public final class VerifyCredentialResponse implements Parcelable {
34 
35     public static final int RESPONSE_ERROR = -1;
36     public static final int RESPONSE_OK = 0;
37     public static final int RESPONSE_RETRY = 1;
38     @IntDef({RESPONSE_ERROR,
39             RESPONSE_OK,
40             RESPONSE_RETRY})
41     @Retention(RetentionPolicy.SOURCE)
42     @interface ResponseCode {}
43 
44     public static final VerifyCredentialResponse OK = new VerifyCredentialResponse.Builder()
45             .build();
46     public static final VerifyCredentialResponse ERROR = fromError();
47     private static final String TAG = "VerifyCredentialResponse";
48 
49     private final @ResponseCode int mResponseCode;
50     private final int mTimeout;
51     @Nullable private final byte[] mGatekeeperHAT;
52     private final long mGatekeeperPasswordHandle;
53 
54     public static final Parcelable.Creator<VerifyCredentialResponse> CREATOR
55             = new Parcelable.Creator<VerifyCredentialResponse>() {
56         @Override
57         public VerifyCredentialResponse createFromParcel(Parcel source) {
58             final @ResponseCode int responseCode = source.readInt();
59             final int timeout = source.readInt();
60             final byte[] gatekeeperHAT = source.createByteArray();
61             long gatekeeperPasswordHandle = source.readLong();
62 
63             return new VerifyCredentialResponse(responseCode, timeout, gatekeeperHAT,
64                     gatekeeperPasswordHandle);
65         }
66 
67         @Override
68         public VerifyCredentialResponse[] newArray(int size) {
69             return new VerifyCredentialResponse[size];
70         }
71     };
72 
73     public static class Builder {
74         @Nullable private byte[] mGatekeeperHAT;
75         private long mGatekeeperPasswordHandle;
76 
77         /**
78          * @param gatekeeperHAT Gatekeeper HardwareAuthToken, minted upon successful authentication.
79          */
setGatekeeperHAT(byte[] gatekeeperHAT)80         public Builder setGatekeeperHAT(byte[] gatekeeperHAT) {
81             mGatekeeperHAT = gatekeeperHAT;
82             return this;
83         }
84 
setGatekeeperPasswordHandle(long gatekeeperPasswordHandle)85         public Builder setGatekeeperPasswordHandle(long gatekeeperPasswordHandle) {
86             mGatekeeperPasswordHandle = gatekeeperPasswordHandle;
87             return this;
88         }
89 
90         /**
91          * Builds a VerifyCredentialResponse with {@link #RESPONSE_OK} and any other parameters
92          * that were preveiously set.
93          * @return
94          */
build()95         public VerifyCredentialResponse build() {
96             return new VerifyCredentialResponse(RESPONSE_OK,
97                     0 /* timeout */,
98                     mGatekeeperHAT,
99                     mGatekeeperPasswordHandle);
100         }
101     }
102 
103     /**
104      * Since timeouts are always an error, provide a way to create the VerifyCredentialResponse
105      * object directly. None of the other fields (Gatekeeper HAT, Gatekeeper Password, etc)
106      * are valid in this case. Similarly, the response code will always be
107      * {@link #RESPONSE_RETRY}.
108      */
fromTimeout(int timeout)109     public static VerifyCredentialResponse fromTimeout(int timeout) {
110         return new VerifyCredentialResponse(RESPONSE_RETRY,
111                 timeout,
112                 null /* gatekeeperHAT */,
113                 0L /* gatekeeperPasswordHandle */);
114     }
115 
116     /**
117      * Since error (incorrect password) should never result in any of the other fields from
118      * being populated, provide a default method to return a VerifyCredentialResponse.
119      */
fromError()120     public static VerifyCredentialResponse fromError() {
121         return new VerifyCredentialResponse(RESPONSE_ERROR,
122                 0 /* timeout */,
123                 null /* gatekeeperHAT */,
124                 0L /* gatekeeperPasswordHandle */);
125     }
126 
VerifyCredentialResponse(@esponseCode int responseCode, int timeout, @Nullable byte[] gatekeeperHAT, long gatekeeperPasswordHandle)127     private VerifyCredentialResponse(@ResponseCode int responseCode, int timeout,
128             @Nullable byte[] gatekeeperHAT, long gatekeeperPasswordHandle) {
129         mResponseCode = responseCode;
130         mTimeout = timeout;
131         mGatekeeperHAT = gatekeeperHAT;
132         mGatekeeperPasswordHandle = gatekeeperPasswordHandle;
133     }
134 
stripPayload()135     public VerifyCredentialResponse stripPayload() {
136         return new VerifyCredentialResponse(mResponseCode, mTimeout,
137                 null /* gatekeeperHAT */, 0L /* gatekeeperPasswordHandle */);
138     }
139 
140     @Override
writeToParcel(Parcel dest, int flags)141     public void writeToParcel(Parcel dest, int flags) {
142         dest.writeInt(mResponseCode);
143         dest.writeInt(mTimeout);
144         dest.writeByteArray(mGatekeeperHAT);
145         dest.writeLong(mGatekeeperPasswordHandle);
146     }
147 
148     @Override
describeContents()149     public int describeContents() {
150         return 0;
151     }
152 
153     @Nullable
getGatekeeperHAT()154     public byte[] getGatekeeperHAT() {
155         return mGatekeeperHAT;
156     }
157 
getGatekeeperPasswordHandle()158     public long getGatekeeperPasswordHandle() {
159         return mGatekeeperPasswordHandle;
160     }
161 
containsGatekeeperPasswordHandle()162     public boolean containsGatekeeperPasswordHandle() {
163         return mGatekeeperPasswordHandle != 0L;
164     }
165 
getTimeout()166     public int getTimeout() {
167         return mTimeout;
168     }
169 
getResponseCode()170     public @ResponseCode int getResponseCode() {
171         return mResponseCode;
172     }
173 
isMatched()174     public boolean isMatched() {
175         return mResponseCode == RESPONSE_OK;
176     }
177 
178     @Override
toString()179     public String toString() {
180         return "Response: " + mResponseCode
181                 + ", GK HAT: " + (mGatekeeperHAT != null)
182                 + ", GK PW: " + (mGatekeeperPasswordHandle != 0L);
183     }
184 
fromGateKeeperResponse( GateKeeperResponse gateKeeperResponse)185     public static VerifyCredentialResponse fromGateKeeperResponse(
186             GateKeeperResponse gateKeeperResponse) {
187         int responseCode = gateKeeperResponse.getResponseCode();
188         if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
189             return fromTimeout(gateKeeperResponse.getTimeout());
190         } else if (responseCode == GateKeeperResponse.RESPONSE_OK) {
191             byte[] token = gateKeeperResponse.getPayload();
192             if (token == null) {
193                 // something's wrong if there's no payload with a challenge
194                 Slog.e(TAG, "verifyChallenge response had no associated payload");
195                 return fromError();
196             } else {
197                 return new VerifyCredentialResponse.Builder().setGatekeeperHAT(token).build();
198             }
199         } else {
200             return fromError();
201         }
202     }
203 }
204