1b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu/*
2b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * Copyright (C) 2017 The Android Open Source Project
3b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu *
4b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * Licensed under the Apache License, Version 2.0 (the "License");
5b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * you may not use this file except in compliance with the License.
6b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * You may obtain a copy of the License at
7b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu *
8b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu *      http://www.apache.org/licenses/LICENSE-2.0
9b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu *
10b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * Unless required by applicable law or agreed to in writing, software
11b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * distributed under the License is distributed on an "AS IS" BASIS,
12b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * See the License for the specific language governing permissions and
14b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu * limitations under the License
15b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu */
16b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
17b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xupackage com.android.server.locksettings;
18b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
19b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xuimport android.os.IProgressListener;
20b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xuimport android.os.RemoteException;
21b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xuimport android.util.ArrayMap;
22b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xuimport android.util.Pair;
23b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
24b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
25b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xuimport junit.framework.AssertionFailedError;
26b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
27b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xuimport java.util.ArrayList;
28b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xuimport java.util.Arrays;
29b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
30b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xupublic class FakeStorageManager {
31b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
32b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    private ArrayMap<Integer, ArrayList<Pair<byte[], byte[]>>> mAuth = new ArrayMap<>();
33b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    private boolean mIgnoreBadUnlock;
34b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
35b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
36b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        getUserAuth(userId).add(new Pair<>(token, secret));
37b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    }
38b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
39b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    public void fixateNewestUserKeyAuth(int userId) {
40b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        ArrayList<Pair<byte[], byte[]>> auths = mAuth.get(userId);
41b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        Pair<byte[], byte[]> latest = auths.get(auths.size() - 1);
42b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        auths.clear();
43b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        auths.add(latest);
44b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    }
45b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
46b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    private ArrayList<Pair<byte[], byte[]>> getUserAuth(int userId) {
47b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        if (!mAuth.containsKey(userId)) {
48b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            ArrayList<Pair<byte[], byte[]>> auths = new ArrayList<Pair<byte[], byte[]>>();
49b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            auths.add(new Pair(null, null));
50b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            mAuth.put(userId,  auths);
51b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        }
52b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        return mAuth.get(userId);
53b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    }
54b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
55b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    public byte[] getUserUnlockToken(int userId) {
56b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        ArrayList<Pair<byte[], byte[]>> auths = getUserAuth(userId);
57b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        if (auths.size() != 1) {
58b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            throw new AssertionFailedError("More than one secret exists");
59b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        }
60b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        return auths.get(0).second;
61b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    }
62b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
63b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    public void unlockUser(int userId, byte[] secret, IProgressListener listener)
64b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            throws RemoteException {
65b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        listener.onStarted(userId, null);
66b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        listener.onFinished(userId, null);
67b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        ArrayList<Pair<byte[], byte[]>> auths = getUserAuth(userId);
68b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        if (secret != null) {
69b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            if (auths.size() > 1) {
70b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu                throw new AssertionFailedError("More than one secret exists");
71b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            }
72b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            Pair<byte[], byte[]> auth = auths.get(0);
73b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            if ((!mIgnoreBadUnlock) && auth.second != null && !Arrays.equals(secret, auth.second)) {
74b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu                throw new AssertionFailedError("Invalid secret to unlock user");
75b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            }
76b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        } else {
77b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            if (auths != null && auths.size() > 0) {
78b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu                throw new AssertionFailedError("Cannot unlock encrypted user with empty token");
79b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu            }
80b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        }
81b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    }
82b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu
83b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    public void setIgnoreBadUnlock(boolean ignore) {
84b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu        mIgnoreBadUnlock = ignore;
85b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu    }
86b31be1b157d9633d43e42b200a92c94e318a4e96Rubin Xu}
87