1b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski/* 2b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * Copyright (C) 2016 The Android Open Source Project 3b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * 4b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * Licensed under the Apache License, Version 2.0 (the "License"); 5b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * you may not use this file except in compliance with the License. 6b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * You may obtain a copy of the License at 7b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * 8b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * http://www.apache.org/licenses/LICENSE-2.0 9b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * 10b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * Unless required by applicable law or agreed to in writing, software 11b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * distributed under the License is distributed on an "AS IS" BASIS, 12b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * See the License for the specific language governing permissions and 14b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski * limitations under the License. 15b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski */ 16b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 17b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskipackage com.android.server.pm; 18b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 19b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport android.app.admin.SecurityLog; 20b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport android.content.Intent; 21b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport android.os.Bundle; 22b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport android.os.Handler; 23b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport android.os.Message; 24b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 25b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport com.android.internal.os.BackgroundThread; 26b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 27b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport java.io.File; 28b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport java.io.FileInputStream; 29b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport java.io.IOException; 30b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport java.security.MessageDigest; 31b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport java.security.NoSuchAlgorithmException; 32b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport java.util.HashMap; 33b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskiimport android.util.Slog; 34b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 35b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinskipublic final class ProcessLoggingHandler extends Handler { 36b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 37b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski private static final String TAG = "ProcessLoggingHandler"; 38b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski static final int LOG_APP_PROCESS_START_MSG = 1; 39b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski static final int INVALIDATE_BASE_APK_HASH_MSG = 2; 40b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 41b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski private final HashMap<String, String> mProcessLoggingBaseApkHashes = new HashMap(); 42b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 43b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski ProcessLoggingHandler() { 44b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski super(BackgroundThread.getHandler().getLooper()); 45b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 46b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 47b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski @Override 48b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski public void handleMessage(Message msg) { 49b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski switch (msg.what) { 50b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski case LOG_APP_PROCESS_START_MSG: { 51b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski Bundle bundle = msg.getData(); 52b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski String processName = bundle.getString("processName"); 53b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski int uid = bundle.getInt("uid"); 54b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski String seinfo = bundle.getString("seinfo"); 55b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski String apkFile = bundle.getString("apkFile"); 56b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski int pid = bundle.getInt("pid"); 57b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski long startTimestamp = bundle.getLong("startTimestamp"); 58b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski String apkHash = computeStringHashOfApk(apkFile); 59b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski SecurityLog.writeEvent(SecurityLog.TAG_APP_PROCESS_START, processName, 60b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski startTimestamp, uid, pid, seinfo, apkHash); 61b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski break; 62b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 63b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski case INVALIDATE_BASE_APK_HASH_MSG: { 64b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski Bundle bundle = msg.getData(); 65b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski mProcessLoggingBaseApkHashes.remove(bundle.getString("apkFile")); 66b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski break; 67b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 68b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 69b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 70b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 71b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski void invalidateProcessLoggingBaseApkHash(String apkPath) { 72b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski Bundle data = new Bundle(); 73b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski data.putString("apkFile", apkPath); 74b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski Message msg = obtainMessage(INVALIDATE_BASE_APK_HASH_MSG); 75b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski msg.setData(data); 76b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski sendMessage(msg); 77b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 78b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 79b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski private String computeStringHashOfApk(String apkFile) { 80b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski if (apkFile == null) { 81b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski return "No APK"; 82b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 83b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski String apkHash = mProcessLoggingBaseApkHashes.get(apkFile); 84b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski if (apkHash == null) { 85b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski try { 86b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski byte[] hash = computeHashOfApkFile(apkFile); 87b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski StringBuilder sb = new StringBuilder(); 88b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski for (int i = 0; i < hash.length; i++) { 89b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski sb.append(String.format("%02x", hash[i])); 90b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 91b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski apkHash = sb.toString(); 92b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski mProcessLoggingBaseApkHashes.put(apkFile, apkHash); 93b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } catch (IOException | NoSuchAlgorithmException e) { 94b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski Slog.w(TAG, "computeStringHashOfApk() failed", e); 95b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 96b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 97b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski return apkHash != null ? apkHash : "Failed to count APK hash"; 98b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 99b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski 100b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski private byte[] computeHashOfApkFile(String packageArchiveLocation) 101b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski throws IOException, NoSuchAlgorithmException { 102b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski MessageDigest md = MessageDigest.getInstance("SHA-256"); 103b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski FileInputStream input = new FileInputStream(new File(packageArchiveLocation)); 104b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski byte[] buffer = new byte[65536]; 105b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski int size; 106b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski while ((size = input.read(buffer)) > 0) { 107b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski md.update(buffer, 0, size); 108b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 109b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski input.close(); 110b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski return md.digest(); 111b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski } 112b52a461851f322b0edf3cb9383da5f449b533311Michal Karpinski} 113