13bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu/*
23bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * Copyright (C) 2017 The Android Open Source Project
33bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu *
43bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * Licensed under the Apache License, Version 2.0 (the "License");
53bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * you may not use this file except in compliance with the License.
63bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * You may obtain a copy of the License at
73bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu *
83bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu *      http://www.apache.org/licenses/LICENSE-2.0
93bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu *
103bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * Unless required by applicable law or agreed to in writing, software
113bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * distributed under the License is distributed on an "AS IS" BASIS,
123bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * See the License for the specific language governing permissions and
143bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu * limitations under the License.
153bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu */
163bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xupackage com.android.server;
173bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
183bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport android.util.ArrayMap;
193bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
203bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport junit.framework.AssertionFailedError;
213bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
223bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport java.nio.ByteBuffer;
233bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport java.security.NoSuchAlgorithmException;
243bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport java.security.spec.InvalidKeySpecException;
253bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport java.util.Arrays;
263bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
273bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport javax.crypto.SecretKeyFactory;
283bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xuimport javax.crypto.spec.PBEKeySpec;
293bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
303bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xupublic class MockSyntheticPasswordManager extends SyntheticPasswordManager {
313bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
323bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    private MockGateKeeperService mGateKeeper;
333bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
343bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    public MockSyntheticPasswordManager(LockSettingsStorage storage,
353bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            MockGateKeeperService gatekeeper) {
363bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        super(storage);
373bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        mGateKeeper = gatekeeper;
383bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
393bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
403bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    private ArrayMap<String, byte[]> mBlobs = new ArrayMap<>();
413bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
423bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    @Override
433bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    protected byte[] decryptSPBlob(String blobKeyName, byte[] blob, byte[] applicationId) {
443bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (mBlobs.containsKey(blobKeyName) && !Arrays.equals(mBlobs.get(blobKeyName), blob)) {
453bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            throw new AssertionFailedError("blobKeyName content is overwritten: " + blobKeyName);
463bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
473bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        ByteBuffer buffer = ByteBuffer.allocate(blob.length);
483bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.put(blob, 0, blob.length);
493bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.flip();
503bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        int len;
513bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        len = buffer.getInt();
523bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        byte[] data = new byte[len];
533bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.get(data);
543bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        len = buffer.getInt();
553bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        byte[] appId = new byte[len];
563bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.get(appId);
573bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        long sid = buffer.getLong();
583bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (!Arrays.equals(appId, applicationId)) {
593bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            throw new AssertionFailedError("Invalid application id");
603bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
613bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        if (sid != 0 && mGateKeeper.getAuthTokenForSid(sid) == null) {
623bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            throw new AssertionFailedError("No valid auth token");
633bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
643bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        return data;
653bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
663bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
673bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    @Override
683bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    protected byte[] createSPBlob(String blobKeyName, byte[] data, byte[] applicationId, long sid) {
693bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES + data.length + Integer.BYTES
703bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu                + applicationId.length + Long.BYTES);
713bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.putInt(data.length);
723bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.put(data);
733bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.putInt(applicationId.length);
743bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.put(applicationId);
753bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        buffer.putLong(sid);
763bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        byte[] result = buffer.array();
773bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        mBlobs.put(blobKeyName, result);
783bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        return result;
793bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
803bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
813bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    @Override
823bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    protected void destroySPBlobKey(String keyAlias) {
833bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
843bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
853bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    @Override
863bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    protected long sidFromPasswordHandle(byte[] handle) {
873bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        return new MockGateKeeperService.VerifyHandle(handle).sid;
883bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
893bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
903bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    @Override
913bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    protected byte[] scrypt(String password, byte[] salt, int N, int r, int p, int outLen) {
923bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        try {
933bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 10, outLen * 8);
943bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
953bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            return f.generateSecret(spec).getEncoded();
963bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
973bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            e.printStackTrace();
983bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu            return null;
993bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu        }
1003bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu    }
1013bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu
1023bf722a8d54ca7192dfe07ee7b73eac7d25ccac5Rubin Xu}
103