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
17package com.android.server.locksettings;
18
19import android.os.IProgressListener;
20import android.os.RemoteException;
21import android.util.ArrayMap;
22import android.util.Pair;
23
24
25import junit.framework.AssertionFailedError;
26
27import java.util.ArrayList;
28import java.util.Arrays;
29
30public class FakeStorageManager {
31
32    private ArrayMap<Integer, ArrayList<Pair<byte[], byte[]>>> mAuth = new ArrayMap<>();
33    private boolean mIgnoreBadUnlock;
34
35    public void addUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
36        getUserAuth(userId).add(new Pair<>(token, secret));
37    }
38
39    public void fixateNewestUserKeyAuth(int userId) {
40        ArrayList<Pair<byte[], byte[]>> auths = mAuth.get(userId);
41        Pair<byte[], byte[]> latest = auths.get(auths.size() - 1);
42        auths.clear();
43        auths.add(latest);
44    }
45
46    private ArrayList<Pair<byte[], byte[]>> getUserAuth(int userId) {
47        if (!mAuth.containsKey(userId)) {
48            ArrayList<Pair<byte[], byte[]>> auths = new ArrayList<Pair<byte[], byte[]>>();
49            auths.add(new Pair(null, null));
50            mAuth.put(userId,  auths);
51        }
52        return mAuth.get(userId);
53    }
54
55    public byte[] getUserUnlockToken(int userId) {
56        ArrayList<Pair<byte[], byte[]>> auths = getUserAuth(userId);
57        if (auths.size() != 1) {
58            throw new AssertionFailedError("More than one secret exists");
59        }
60        return auths.get(0).second;
61    }
62
63    public void unlockUser(int userId, byte[] secret, IProgressListener listener)
64            throws RemoteException {
65        listener.onStarted(userId, null);
66        listener.onFinished(userId, null);
67        ArrayList<Pair<byte[], byte[]>> auths = getUserAuth(userId);
68        if (secret != null) {
69            if (auths.size() > 1) {
70                throw new AssertionFailedError("More than one secret exists");
71            }
72            Pair<byte[], byte[]> auth = auths.get(0);
73            if ((!mIgnoreBadUnlock) && auth.second != null && !Arrays.equals(secret, auth.second)) {
74                throw new AssertionFailedError("Invalid secret to unlock user");
75            }
76        } else {
77            if (auths != null && auths.size() > 0) {
78                throw new AssertionFailedError("Cannot unlock encrypted user with empty token");
79            }
80        }
81    }
82
83    public void setIgnoreBadUnlock(boolean ignore) {
84        mIgnoreBadUnlock = ignore;
85    }
86}
87