MockSyntheticPasswordManager.java revision 7374d3a4bca6bfbf7da1ef5dbf0db9f35f0c8315
19439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly/*
28949bfb90c415629dbd0e30d25003fb3e0375fb5Hemant Gupta * Copyright (C) 2017 The Android Open Source Project
39439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
49439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
59439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * you may not use this file except in compliance with the License.
69439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * You may obtain a copy of the License at
79439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
89439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
99439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly *
109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * Unless required by applicable law or agreed to in writing, software
119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * See the License for the specific language governing permissions and
149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly * limitations under the License.
159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly */
169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypackage com.android.server.locksettings;
179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
189439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.hardware.weaver.V1_0.IWeaver;
199439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.os.RemoteException;
209439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.os.UserManager;
219439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport android.util.ArrayMap;
229439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
239439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport junit.framework.AssertionFailedError;
249439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
259439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.nio.ByteBuffer;
269439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.security.NoSuchAlgorithmException;
279439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.security.spec.InvalidKeySpecException;
289439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport java.util.Arrays;
299439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
309439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport javax.crypto.SecretKeyFactory;
319439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellyimport javax.crypto.spec.PBEKeySpec;
329439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
339439a7fe517b858bc5e5c654b459315e4722feb2Nick Pellypublic class MockSyntheticPasswordManager extends SyntheticPasswordManager {
349439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
359439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    private MockGateKeeperService mGateKeeper;
362e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly    private IWeaver mWeaverService;
372e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly
382e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly    public MockSyntheticPasswordManager(LockSettingsStorage storage,
3925f2c4cd953764008d04147a14d990c06a8154e5Oscar Montemayor            MockGateKeeperService gatekeeper, UserManager userManager) {
409439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        super(storage, userManager);
419439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        mGateKeeper = gatekeeper;
429439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
43238e0f934f1f47263b384bc745ae0678c777130dCasper Bonde
442e0da96e757a977154063f980d3f4e1abd41cf09Nick Pelly    private ArrayMap<String, byte[]> mBlobs = new ArrayMap<>();
459439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
469439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    @Override
479439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    protected byte[] decryptSPBlob(String blobKeyName, byte[] blob, byte[] applicationId) {
489439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (mBlobs.containsKey(blobKeyName) && !Arrays.equals(mBlobs.get(blobKeyName), blob)) {
4905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun            throw new AssertionFailedError("blobKeyName content is overwritten: " + blobKeyName);
5005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun        }
519439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ByteBuffer buffer = ByteBuffer.allocate(blob.length);
529439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        buffer.put(blob, 0, blob.length);
539439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        buffer.flip();
549439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        int len;
559439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        len = buffer.getInt();
569439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] data = new byte[len];
5705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun        buffer.get(data);
589439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        len = buffer.getInt();
599439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        byte[] appId = new byte[len];
609439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        buffer.get(appId);
619439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        long sid = buffer.getLong();
629439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (!Arrays.equals(appId, applicationId)) {
639439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new AssertionFailedError("Invalid application id");
6405ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun        }
659439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        if (sid != 0 && mGateKeeper.getAuthTokenForSid(sid) == null) {
669439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            throw new AssertionFailedError("No valid auth token");
679439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
689439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return data;
699439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
709439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
719439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    @Override
7205ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    protected byte[] createSPBlob(String blobKeyName, byte[] data, byte[] applicationId, long sid) {
739439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES + data.length + Integer.BYTES
749439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly                + applicationId.length + Long.BYTES);
759439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        buffer.putInt(data.length);
769439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        buffer.put(data);
779439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        buffer.putInt(applicationId.length);
789439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        buffer.put(applicationId);
799439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        buffer.putLong(sid);
8005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun        byte[] result = buffer.array();
8105ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun        mBlobs.put(blobKeyName, result);
829439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return result;
839439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
849439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
859439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    @Override
869439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    protected void destroySPBlobKey(String keyAlias) {
879439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
8805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun
8905ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    @Override
9005ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun    protected long sidFromPasswordHandle(byte[] handle) {
919439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return new MockGateKeeperService.VerifyHandle(handle).sid;
929439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
939439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
949439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    @Override
959439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    protected byte[] scrypt(String password, byte[] salt, int N, int r, int p, int outLen) {
969439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        try {
9705ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun            PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 10, outLen * 8);
9805ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun            SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
999439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return f.generateSecret(spec).getEncoded();
1009439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
1019439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            e.printStackTrace();
1029439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly            return null;
1039439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        }
1049439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
10505ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun
1069439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    @Override
1079439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    protected IWeaver getWeaverService() throws RemoteException {
1089439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        return mWeaverService;
1099439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1109439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1119439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    public void enableWeaver() {
1129439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly        mWeaverService = new MockWeaverService();
11305ff98bbefda39b9ff26f8bca132cfd0248745c6Tao Liejun        initWeaverService();
1149439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly    }
1159439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly
1169439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly}
1179439a7fe517b858bc5e5c654b459315e4722feb2Nick Pelly