OSDN Git Service

[automerger skipped] Import translations. DO NOT MERGE skipped: f6e12d6972 skipped...
[android-x86/frameworks-base.git] / services / tests / servicestests / src / com / android / server / MockGateKeeperService.java
1 /*
2  * Copyright (C) 2017 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.server;
18
19 import android.os.IBinder;
20 import android.os.RemoteException;
21 import android.service.gatekeeper.GateKeeperResponse;
22 import android.service.gatekeeper.IGateKeeperService;
23 import android.util.ArrayMap;
24
25 import junit.framework.AssertionFailedError;
26
27 import java.nio.ByteBuffer;
28 import java.util.Arrays;
29 import java.util.Random;
30
31 public class MockGateKeeperService implements IGateKeeperService {
32     static class VerifyHandle {
33         public byte[] password;
34         public long sid;
35
36         public VerifyHandle(byte[] password, long sid) {
37             this.password = password;
38             this.sid = sid;
39         }
40
41         public VerifyHandle(byte[] handle) {
42             ByteBuffer buffer = ByteBuffer.allocate(handle.length);
43             buffer.put(handle, 0, handle.length);
44             buffer.flip();
45             int version = buffer.get();
46             sid = buffer.getLong();
47             password = new byte[buffer.remaining()];
48             buffer.get(password);
49         }
50
51         public byte[] toBytes() {
52             ByteBuffer buffer = ByteBuffer.allocate(1 + Long.BYTES + password.length);
53             buffer.put((byte)0);
54             buffer.putLong(sid);
55             buffer.put(password);
56             return buffer.array();
57         }
58     }
59
60     static class AuthToken {
61         public long challenge;
62         public long sid;
63
64         public AuthToken(long challenge, long sid) {
65             this.challenge = challenge;
66             this.sid = sid;
67         }
68
69         public AuthToken(byte[] handle) {
70             ByteBuffer buffer = ByteBuffer.allocate(handle.length);
71             buffer.put(handle, 0, handle.length);
72             buffer.flip();
73             int version = buffer.get();
74             challenge = buffer.getLong();
75             sid = buffer.getLong();
76         }
77
78         public byte[] toBytes() {
79             ByteBuffer buffer = ByteBuffer.allocate(1 + Long.BYTES + Long.BYTES);
80             buffer.put((byte)0);
81             buffer.putLong(challenge);
82             buffer.putLong(sid);
83             return buffer.array();
84         }
85     }
86
87     private ArrayMap<Integer, Long> sidMap = new ArrayMap<>();
88     private ArrayMap<Integer, AuthToken> authTokenMap = new ArrayMap<>();
89
90     private ArrayMap<Integer, byte[]> handleMap = new ArrayMap<>();
91
92     @Override
93     public GateKeeperResponse enroll(int uid, byte[] currentPasswordHandle, byte[] currentPassword,
94             byte[] desiredPassword) throws android.os.RemoteException {
95
96         if (currentPasswordHandle != null) {
97             VerifyHandle handle = new VerifyHandle(currentPasswordHandle);
98             if (Arrays.equals(currentPassword, handle.password)) {
99                 // Trusted enroll
100                 VerifyHandle newHandle = new VerifyHandle(desiredPassword, handle.sid);
101                 refreshSid(uid, handle.sid, false);
102                 handleMap.put(uid, newHandle.toBytes());
103                 return GateKeeperResponse.createOkResponse(newHandle.toBytes(), false);
104             } else {
105                 return null;
106             }
107         } else {
108             // Untrusted enroll
109             long newSid = new Random().nextLong();
110             VerifyHandle newHandle = new VerifyHandle(desiredPassword, newSid);
111             refreshSid(uid, newSid, true);
112             handleMap.put(uid, newHandle.toBytes());
113             return GateKeeperResponse.createOkResponse(newHandle.toBytes(), false);
114         }
115     }
116
117     @Override
118     public GateKeeperResponse verify(int uid, byte[] enrolledPasswordHandle,
119             byte[] providedPassword) throws android.os.RemoteException {
120         return verifyChallenge(uid, 0, enrolledPasswordHandle, providedPassword);
121     }
122
123     @Override
124     public GateKeeperResponse verifyChallenge(int uid, long challenge,
125             byte[] enrolledPasswordHandle, byte[] providedPassword) throws RemoteException {
126
127         VerifyHandle handle = new VerifyHandle(enrolledPasswordHandle);
128         if (Arrays.equals(handle.password, providedPassword)) {
129             byte[] knownHandle = handleMap.get(uid);
130             if (knownHandle != null) {
131                 if (!Arrays.equals(knownHandle, enrolledPasswordHandle)) {
132                     throw new AssertionFailedError("Got correct but obsolete handle");
133                 }
134             }
135             refreshSid(uid, handle.sid, false);
136             AuthToken token = new AuthToken(challenge, handle.sid);
137             refreshAuthToken(uid, token);
138             return GateKeeperResponse.createOkResponse(token.toBytes(), false);
139         } else {
140             return GateKeeperResponse.createGenericResponse(GateKeeperResponse.RESPONSE_ERROR);
141         }
142     }
143
144     private void refreshAuthToken(int uid, AuthToken token) {
145         authTokenMap.put(uid, token);
146     }
147
148     public AuthToken getAuthToken(int uid) {
149         return authTokenMap.get(uid);
150     }
151
152     public AuthToken getAuthTokenForSid(long sid) {
153         for(AuthToken token : authTokenMap.values()) {
154             if (token.sid == sid) {
155                 return token;
156             }
157         }
158         return null;
159     }
160
161     public void clearAuthToken(int uid) {
162         authTokenMap.remove(uid);
163     }
164
165     @Override
166     public IBinder asBinder() {
167         throw new UnsupportedOperationException();
168     }
169
170     @Override
171     public void clearSecureUserId(int userId) throws RemoteException {
172         sidMap.remove(userId);
173     }
174
175     @Override
176     public long getSecureUserId(int userId) throws RemoteException {
177         if (sidMap.containsKey(userId)) {
178             return sidMap.get(userId);
179         } else {
180             return 0L;
181         }
182     }
183
184     private void refreshSid(int uid, long sid, boolean force) {
185         if (!sidMap.containsKey(uid) || force) {
186             sidMap.put(uid, sid);
187         } else{
188             if (sidMap.get(uid) != sid) {
189                 throw new AssertionFailedError("Inconsistent SID");
190             }
191         }
192     }
193
194 }