MockSyntheticPasswordManager.java revision 3bf722a8d54ca7192dfe07ee7b73eac7d25ccac5
17d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang/* 27d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * Copyright (C) 2017 The Android Open Source Project 37d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * 47d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * Licensed under the Apache License, Version 2.0 (the "License"); 57d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * you may not use this file except in compliance with the License. 67d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * You may obtain a copy of the License at 77d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * 87d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * http://www.apache.org/licenses/LICENSE-2.0 97d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * 107d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * Unless required by applicable law or agreed to in writing, software 117d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * distributed under the License is distributed on an "AS IS" BASIS, 127d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * See the License for the specific language governing permissions and 147d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang * limitations under the License. 157d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang */ 167d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangpackage com.android.server; 177d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 187d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangimport android.util.ArrayMap; 197d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 207d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangimport junit.framework.AssertionFailedError; 217d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 227d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangimport java.nio.ByteBuffer; 237d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangimport java.security.NoSuchAlgorithmException; 247d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangimport java.security.spec.InvalidKeySpecException; 257d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangimport java.util.Arrays; 267d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 277d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangimport javax.crypto.SecretKeyFactory; 287d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangimport javax.crypto.spec.PBEKeySpec; 297d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 307d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wangpublic class MockSyntheticPasswordManager extends SyntheticPasswordManager { 317d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 327d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang private MockGateKeeperService mGateKeeper; 337d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 347d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang public MockSyntheticPasswordManager(LockSettingsStorage storage, 357d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang MockGateKeeperService gatekeeper) { 367d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang super(storage); 377d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang mGateKeeper = gatekeeper; 387d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 397d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 407d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang private ArrayMap<String, byte[]> mBlobs = new ArrayMap<>(); 417d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 427d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang @Override 437d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang protected byte[] decryptSPBlob(String blobKeyName, byte[] blob, byte[] applicationId) { 447d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang if (mBlobs.containsKey(blobKeyName) && !Arrays.equals(mBlobs.get(blobKeyName), blob)) { 457d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang throw new AssertionFailedError("blobKeyName content is overwritten: " + blobKeyName); 467d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 477d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang ByteBuffer buffer = ByteBuffer.allocate(blob.length); 487d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.put(blob, 0, blob.length); 497d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.flip(); 507d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang int len; 517d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang len = buffer.getInt(); 527d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang byte[] data = new byte[len]; 537d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.get(data); 547d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang len = buffer.getInt(); 557d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang byte[] appId = new byte[len]; 567d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.get(appId); 577d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang long sid = buffer.getLong(); 587d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang if (!Arrays.equals(appId, applicationId)) { 597d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang throw new AssertionFailedError("Invalid application id"); 607d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 617d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang if (sid != 0 && mGateKeeper.getAuthTokenForSid(sid) == null) { 627d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang throw new AssertionFailedError("No valid auth token"); 637d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 647d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang return data; 657d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 667d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 677d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang @Override 687d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang protected byte[] createSPBlob(String blobKeyName, byte[] data, byte[] applicationId, long sid) { 697d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES + data.length + Integer.BYTES 707d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang + applicationId.length + Long.BYTES); 717d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.putInt(data.length); 727d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.put(data); 737d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.putInt(applicationId.length); 747d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.put(applicationId); 757d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang buffer.putLong(sid); 767d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang byte[] result = buffer.array(); 777d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang mBlobs.put(blobKeyName, result); 787d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang return result; 797d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 807d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 817d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang @Override 827d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang protected void destroySPBlobKey(String keyAlias) { 837d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 847d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 857d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang @Override 867d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang protected long sidFromPasswordHandle(byte[] handle) { 877d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang return new MockGateKeeperService.VerifyHandle(handle).sid; 887d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 897d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 907d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang @Override 917d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang protected byte[] scrypt(String password, byte[] salt, int N, int r, int p, int outLen) { 927d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang try { 937d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 10, outLen * 8); 947d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang SecretKeyFactory f = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); 957d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang return f.generateSecret(spec).getEncoded(); 967d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { 977d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang e.printStackTrace(); 987d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang return null; 997d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 1007d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang } 1017d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang 1027d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang} 1037d1bbca7d1b6cef9515a3ad672c7ae71ff5ba69bMiao Wang