KeySetManagerService.java revision 7664bceec3422f55db46d7d1bf908ae6110a6548
1d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase/* 2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright (C) 2013 The Android Open Source Project 3d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 4d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Licensed under the Apache License, Version 2.0 (the "License"); 5d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * you may not use this file except in compliance with the License. 6d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * You may obtain a copy of the License at 7d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 8d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * http://www.apache.org/licenses/LICENSE-2.0 9d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * 10d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Unless required by applicable law or agreed to in writing, software 11d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * distributed under the License is distributed on an "AS IS" BASIS, 12d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * See the License for the specific language governing permissions and 14d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * limitations under the License. 15d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 16d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage com.android.server.pm; 18d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; 20959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 2142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport com.android.internal.util.Preconditions; 2242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.content.pm.PackageParser; 2342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.ArrayMap; 2442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.ArraySet; 2542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.Base64; 2642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.Slog; 2742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport android.util.LongSparseArray; 2842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 2942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport java.io.IOException; 3042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikasimport java.io.PrintWriter; 310a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport java.security.PublicKey; 322bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyarimport java.util.Set; 33c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar 348ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyarimport org.xmlpull.v1.XmlPullParser; 350a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.xmlpull.v1.XmlPullParserException; 360a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport org.xmlpull.v1.XmlSerializer; 37d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 38e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar/* 39d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * Manages system-wide KeySet state. 40d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 41310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyarpublic class KeySetManagerService { 42d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 43d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase static final String TAG = "KeySetManagerService"; 44c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas 45c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas /* original keysets implementation had no versioning info, so this is the first */ 46c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas public static final int FIRST_VERSION = 1; 47c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas 48c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas public static final int CURRENT_VERSION = FIRST_VERSION; 49c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas 5042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas /** Sentinel value returned when a {@code KeySet} is not found. */ 5142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas public static final long KEYSET_NOT_FOUND = -1; 5242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 5342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas /** Sentinel value returned when public key is not found. */ 5442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas protected static final long PUBLIC_KEY_NOT_FOUND = -1; 5542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 562bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar private final LongSparseArray<KeySetHandle> mKeySets; 572bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar 58d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private final LongSparseArray<PublicKeyHandle> mPublicKeys; 5990ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar 60d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase protected final LongSparseArray<ArraySet<Long>> mKeySetMapping; 6190ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar 62d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private final ArrayMap<String, PackageSetting> mPackages; 63d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 64959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar private long lastIssuedKeySetId = 0; 6511b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar 6666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar private long lastIssuedKeyId = 0; 670a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 68d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase class PublicKeyHandle { 69d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private final PublicKey mKey; 70d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase private final long mId; 71b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar private int mRefCount; 72b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 73b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public PublicKeyHandle(long id, PublicKey key) { 74d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mId = id; 758ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mRefCount = 1; 768ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar mKey = key; 7766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } 7866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar 7966826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar /* 807e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar * Only used when reading state from packages.xml 81e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar */ 82e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar private PublicKeyHandle(long id, int refCount, PublicKey key) { 830a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mId = id; 8467171c81b114f5a858dd55ec712cb584f255fc93Aurimas Liutikas mRefCount = refCount; 8567171c81b114f5a858dd55ec712cb584f255fc93Aurimas Liutikas mKey = key; 860a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 87d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 88b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public long getId() { 89b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar return mId; 90b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 91b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 92b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar public PublicKey getKey() { 93b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar return mKey; 94b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 957e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar 9666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar public int getRefCountLPr() { 9766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar return mRefCount; 987e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar } 997e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar 1007e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar public void incrRefCountLPw() { 10166826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar mRefCount++; 10266826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar return; 10366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } 10466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar 10566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar public long decrRefCountLPw() { 10666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar mRefCount--; 10766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar return mRefCount; 10866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } 1090a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar } 1100a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 1110a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public KeySetManagerService(ArrayMap<String, PackageSetting> packages) { 1120a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mKeySets = new LongSparseArray<KeySetHandle>(); 1130a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mPublicKeys = new LongSparseArray<PublicKeyHandle>(); 1140a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar mKeySetMapping = new LongSparseArray<ArraySet<Long>>(); 115e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar mPackages = packages; 1169f5e74d12c89334c2bd439b1bf19fdc5ebfbc137Aurimas Liutikas } 117e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar 118e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar /** 119e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar * Determine if a package is signed by the given KeySet. 120e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar * 12142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas * Returns false if the package was not signed by all the 122e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar * keys in the KeySet. 123e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar * 124e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar * Returns true if the package was signed by at least the 125e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar * keys in the given KeySet. 126e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar * 127e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar * Note that this can return true for multiple KeySets. 128e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar */ 129e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar public boolean packageIsSignedByLPr(String packageName, KeySetHandle ks) { 130e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar PackageSetting pkg = mPackages.get(packageName); 131e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar if (pkg == null) { 132959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar throw new NullPointerException("Invalid package name"); 133959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 134959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar if (pkg.keySetData == null) { 135959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar throw new NullPointerException("Package has no KeySet data"); 1362bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar } 1372bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar long id = getIdByKeySetLPr(ks); 1382bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar if (id == KEYSET_NOT_FOUND) { 1390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar return false; 1402bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar } 1412bf89a9bae2b6110a77cf0b3754b567bb07d12a5Yigit Boyar ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet()); 1420b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar ArraySet<Long> testKeys = mKeySetMapping.get(id); 14342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas return pkgKeys.containsAll(testKeys); 1440b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar } 1450b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar 1460b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar /** 1470b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * Determine if a package is signed by the given KeySet. 1480b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * 1490b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * Returns false if the package was not signed by all the 1500b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * keys in the KeySet, or if the package was signed by keys 1519c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * not in the KeySet. 1529c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * 1539c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri * Note that this can return only for one KeySet. 1549c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri */ 1559c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri public boolean packageIsSignedByExactlyLPr(String packageName, KeySetHandle ks) { 156f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar PackageSetting pkg = mPackages.get(packageName); 157d8d42d52f8ae53107ffa849b86496650182e24b8Yigit Boyar if (pkg == null) { 15842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas throw new NullPointerException("Invalid package name"); 159f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar } 160f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar if (pkg.keySetData == null 161f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar || pkg.keySetData.getProperSigningKeySet() 162f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar == PackageKeySetData.KEYSET_UNASSIGNED) { 163f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar throw new NullPointerException("Package has no KeySet data"); 164f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar } 165d8d42d52f8ae53107ffa849b86496650182e24b8Yigit Boyar long id = getIdByKeySetLPr(ks); 166f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar if (id == KEYSET_NOT_FOUND) { 167f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar return false; 1689c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri } 1699c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri ArraySet<Long> pkgKeys = mKeySetMapping.get(pkg.keySetData.getProperSigningKeySet()); 1709c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri ArraySet<Long> testKeys = mKeySetMapping.get(id); 171d8d42d52f8ae53107ffa849b86496650182e24b8Yigit Boyar return pkgKeys.equals(testKeys); 172f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar } 173f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar 174e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar /** 175e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * addScannedPackageLPw directly modifies the package metadata in pm.Settings 176e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * at a point of no-return. We need to make sure that the scanned package does 177e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * not contain bad keyset meta-data that could generate an incorrect 178e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * PackageSetting. Verify that there is a signing keyset, there are no issues 179e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * with null objects, and the upgrade and defined keysets match. 1800b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * 1810b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * Returns true if the package can safely be added to the keyset metadata. 18242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas */ 1830b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar public void assertScannedPackageValid(PackageParser.Package pkg) 1840b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar throws PackageManagerException { 185824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar if (pkg == null || pkg.packageName == null) { 186824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 187824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar "Passed invalid package to keyset validation."); 188824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar } 189824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar ArraySet<PublicKey> signingKeys = pkg.mSigningKeys; 1900b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar if (signingKeys == null || !(signingKeys.size() > 0) || signingKeys.contains(null)) { 1910b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 192824a7db96feacf3b68f56993ed72712bc935153eYigit Boyar "Package has invalid signing-key-set."); 1930b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar } 1940b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar ArrayMap<String, ArraySet<PublicKey>> definedMapping = pkg.mKeySetMapping; 1957e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar if (definedMapping != null) { 196e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar if (definedMapping.containsKey(null) || definedMapping.containsValue(null)) { 197e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 198e05fbd9cfe05496e82a3abe19e07e8745985e9a5Yigit Boyar "Package has null defined key set."); 19966826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } 2006e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar int defMapSize = definedMapping.size(); 2016e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar for (int i = 0; i < defMapSize; i++) { 20290ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar if (!(definedMapping.valueAt(i).size() > 0) 20366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar || definedMapping.valueAt(i).contains(null)) { 2046e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 2056e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar "Package has null/no public keys for defined key-sets."); 2067e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar } 2077e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar } 2087e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar } 2097e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar ArraySet<String> upgradeAliases = pkg.mUpgradeKeySets; 2107f5e94985f795f81884334ca2752a0469a998762Yigit Boyar if (upgradeAliases != null) { 2117f5e94985f795f81884334ca2752a0469a998762Yigit Boyar if (definedMapping == null || !(definedMapping.keySet().containsAll(upgradeAliases))) { 2127f5e94985f795f81884334ca2752a0469a998762Yigit Boyar throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, 2137f5e94985f795f81884334ca2752a0469a998762Yigit Boyar "Package has upgrade-key-sets without corresponding definitions."); 2147e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar } 2157e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar } 2167e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar } 2177e9da1a2629b657d56e2f54abd18c6249f3be037Yigit Boyar 2180a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void addScannedPackageLPw(PackageParser.Package pkg) { 2190a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar Preconditions.checkNotNull(pkg, "Attempted to add null pkg to ksms."); 2200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar Preconditions.checkNotNull(pkg.packageName, "Attempted to add null pkg to ksms."); 2210a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar PackageSetting ps = mPackages.get(pkg.packageName); 2220a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar Preconditions.checkNotNull(ps, "pkg: " + pkg.packageName 2230a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar + "does not have a corresponding entry in mPackages."); 2248ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar addSigningKeySetToPackageLPw(ps, pkg.mSigningKeys); 2258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (pkg.mKeySetMapping != null) { 2268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar addDefinedKeySetsToPackageLPw(ps, pkg.mKeySetMapping); 2278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar if (pkg.mUpgradeKeySets != null) { 2288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar addUpgradeKeySetsToPackageLPw(ps, pkg.mUpgradeKeySets); 2298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2308ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 2318ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 232ca9ce7ccdccf6b6a2a81da73dd1e6425d90e4b23Yigit Boyar 2336e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar /** 2346e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar * Informs the system that the given package was signed by the provided KeySet. 2356e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar */ 2366e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar void addSigningKeySetToPackageLPw(PackageSetting pkg, 2376e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar ArraySet<PublicKey> signingKeys) { 238121ba9616e5bed44d2490f1744f7b6a9d3e79866Yigit Boyar 2396e83751247c5be0211d7bffaf057431c03dfef38Yigit Boyar /* check existing keyset for reuse or removal */ 2408ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar long signingKeySetId = pkg.keySetData.getProperSigningKeySet(); 2418ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 242c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar if (signingKeySetId != PackageKeySetData.KEYSET_UNASSIGNED) { 243c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar ArraySet<PublicKey> existingKeys = getPublicKeysFromKeySetLPr(signingKeySetId); 244c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar if (existingKeys != null && existingKeys.equals(signingKeys)) { 245c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar 24629c349ed8863cc15c2580465227c37771ac49576Yigit Boyar /* no change in signing keys, leave PackageSetting alone */ 24729c349ed8863cc15c2580465227c37771ac49576Yigit Boyar return; 248c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar } else { 249c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar 250c50c4cad31d73e574b27bb3d7581542975e37263Yigit Boyar /* old keyset no longer valid, remove ref */ 251b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar decrementKeySetLPw(signingKeySetId); 252d7e2f2ab1d253133fa54f309e74a7ee384c33971Yigit Boyar } 253d7e2f2ab1d253133fa54f309e74a7ee384c33971Yigit Boyar } 254d7e2f2ab1d253133fa54f309e74a7ee384c33971Yigit Boyar 25590ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar /* create and add a new keyset */ 25690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar KeySetHandle ks = addKeySetLPw(signingKeys); 25790ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar long id = ks.getId(); 25842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas pkg.keySetData.setProperSigningKeySet(id); 259b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar return; 260b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 261abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar 26266826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar /** 26366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar * Fetches the stable identifier associated with the given KeySet. Returns 26466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found. 26566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar */ 26666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar private long getIdByKeySetLPr(KeySetHandle ks) { 26766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) { 26866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar KeySetHandle value = mKeySets.valueAt(keySetIndex); 269abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar if (ks.equals(value)) { 270a90fb62f06861beb3af9f9b3356ef0bb0685547cYigit Boyar return mKeySets.keyAt(keySetIndex); 271abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar } 272abd0fbfcdd5b438909f126392eca5978b5939b6dYigit Boyar } 27390ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar return KEYSET_NOT_FOUND; 274b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 275b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 27690ca3086dbf66ad6bb8840e46ec8524a705e1c18Yigit Boyar /** 277b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * Inform the system that the given package defines the given KeySets. 278b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * Remove any KeySets the package no longer defines. 2799051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar */ 2809051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar void addDefinedKeySetsToPackageLPw(PackageSetting pkg, 28142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas ArrayMap<String, ArraySet<PublicKey>> definedMapping) { 2829051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar ArrayMap<String, Long> prevDefinedKeySets = pkg.keySetData.getAliases(); 2839051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 2849051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar /* add all of the newly defined KeySets */ 2859051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar ArrayMap<String, Long> newKeySetAliases = new ArrayMap<String, Long>(); 2869051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar final int defMapSize = definedMapping.size(); 2879051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar for (int i = 0; i < defMapSize; i++) { 2889051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar String alias = definedMapping.keyAt(i); 2899051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar ArraySet<PublicKey> pubKeys = definedMapping.valueAt(i); 2909051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar if (alias != null && pubKeys != null && pubKeys.size() > 0) { 2919051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar KeySetHandle ks = addKeySetLPw(pubKeys); 2929051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar newKeySetAliases.put(alias, ks.getId()); 2939051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 2949051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar } 2959051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar 296504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar /* remove each of the old references */ 297504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar final int prevDefSize = prevDefinedKeySets.size(); 298959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar for (int i = 0; i < prevDefSize; i++) { 299959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar decrementKeySetLPw(prevDefinedKeySets.valueAt(i)); 30042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas } 301959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar pkg.keySetData.removeAllUpgradeKeySets(); 302959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 303959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar /* switch to the just-added */ 304959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar pkg.keySetData.setAliases(newKeySetAliases); 305959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar return; 306959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 307959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 308959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar /** 309959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar * This informs the system that the given package has defined a KeySet 310959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar * alias in its manifest to be an upgradeKeySet. This must be called 311959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar * after all of the defined KeySets have been added. 312959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar */ 313959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar void addUpgradeKeySetsToPackageLPw(PackageSetting pkg, 314959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar ArraySet<String> upgradeAliases) { 315959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar final int uaSize = upgradeAliases.size(); 316959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar for (int i = 0; i < uaSize; i++) { 317959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar pkg.keySetData.addUpgradeKeySet(upgradeAliases.valueAt(i)); 318959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 319959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar return; 320959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 321959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 322959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar /** 323542f1260934df280985294eaef1ec8469863281fYigit Boyar * Fetched the {@link KeySetHandle} that a given package refers to by the 32442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas * provided alias. Returns null if the package is unknown or does not have a 32542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas * KeySet corresponding to that alias. 32642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas */ 32742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas public KeySetHandle getKeySetByAliasAndPackageNameLPr(String packageName, String alias) { 32842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas PackageSetting p = mPackages.get(packageName); 32942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas if (p == null || p.keySetData == null) { 330046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard return null; 331046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard } 332046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard Long keySetId = p.keySetData.getAliases().get(alias); 333046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard if (keySetId == null) { 334046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard throw new IllegalArgumentException("Unknown KeySet alias: " + alias); 335046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard } 336959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar return mKeySets.get(keySetId); 337959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 338959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 339542f1260934df280985294eaef1ec8469863281fYigit Boyar /* Checks if an identifier refers to a known keyset */ 340542f1260934df280985294eaef1ec8469863281fYigit Boyar public boolean isIdValidKeySetId(long id) { 341542f1260934df280985294eaef1ec8469863281fYigit Boyar return mKeySets.get(id) != null; 342b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 3430b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar 3440b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar /** 3450b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * Fetches the {@link PublicKey public keys} which belong to the specified 3460b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * KeySet id. 347f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes * 348e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar * Returns {@code null} if the identifier doesn't 349e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar * identify a {@link KeySetHandle}. 350e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar */ 351e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar public ArraySet<PublicKey> getPublicKeysFromKeySetLPr(long id) { 352b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar ArraySet<Long> pkIds = mKeySetMapping.get(id); 3530b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar if (pkIds == null) { 3540b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar return null; 3550b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar } 3560b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar ArraySet<PublicKey> mPubKeys = new ArraySet<PublicKey>(); 3570b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar final int pkSize = pkIds.size(); 3580b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar for (int i = 0; i < pkSize; i++) { 3590b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar mPubKeys.add(mPublicKeys.get(pkIds.valueAt(i)).getKey()); 3600b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar } 3610b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar return mPubKeys; 3620b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar } 3630b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar 3640b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar /** 3650b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * Fetches the proper {@link KeySetHandle KeySet} that signed the given 3668da5bba529a2fe9bd2aafab28010e11ec4de93c7Yigit Boyar * package. 3678da5bba529a2fe9bd2aafab28010e11ec4de93c7Yigit Boyar * 3680b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * @throws IllegalArgumentException if the package has no keyset data. 3690b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar * @throws NullPointerException if the packgae is unknown. 370619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar */ 3710b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar public KeySetHandle getSigningKeySetByPackageNameLPr(String packageName) { 3720b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar PackageSetting p = mPackages.get(packageName); 3730b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar if (p == null 3740b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar || p.keySetData == null 3750b1059b711009601ff08354e2df6bfc45266e80aYigit Boyar || p.keySetData.getProperSigningKeySet() 376e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar == PackageKeySetData.KEYSET_UNASSIGNED) { 377e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar return null; 378e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar } 379e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar return mKeySets.get(p.keySetData.getProperSigningKeySet()); 380e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar } 381e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar 382e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar /** 383e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar * Creates a new KeySet corresponding to the given keys. 3840a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * 3850a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar * If the {@link PublicKey PublicKeys} aren't known to the system, this 386e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar * adds them. Otherwise, they're deduped and the reference count 387e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar * incremented. 388e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar * 389e37d2e63f16bc5c2938e372238ba54679a9e578eYigit Boyar * If the KeySet isn't known to the system, this adds that and creates the 3908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar * mapping to the PublicKeys. If it is known, then it's deduped and the 39142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas * reference count is incremented. 392b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * 393b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar * Throws if the provided set is {@code null}. 394a90fb62f06861beb3af9f9b3356ef0bb0685547cYigit Boyar */ 395b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar private KeySetHandle addKeySetLPw(ArraySet<PublicKey> keys) { 396b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (keys == null || keys.size() == 0) { 397b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar throw new IllegalArgumentException("Cannot add an empty set of keys!"); 398b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 399310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyar 400a90fb62f06861beb3af9f9b3356ef0bb0685547cYigit Boyar /* add each of the keys in the provided set */ 401310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyar ArraySet<Long> addedKeyIds = new ArraySet<Long>(keys.size()); 402310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyar final int kSize = keys.size(); 40342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas for (int i = 0; i < kSize; i++) { 40442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas long id = addPublicKeyLPw(keys.valueAt(i)); 40542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas addedKeyIds.add(id); 40642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas } 40742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 40842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas /* check to see if the resulting keyset is new */ 40942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas long existingKeySetId = getIdFromKeyIdsLPr(addedKeyIds); 410b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (existingKeySetId != KEYSET_NOT_FOUND) { 411b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar 41242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas /* public keys were incremented, but we aren't adding a new keyset: undo */ 41342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas for (int i = 0; i < kSize; i++) { 41442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas decrementPublicKeyLPw(addedKeyIds.valueAt(i)); 41542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas } 41642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas KeySetHandle ks = mKeySets.get(existingKeySetId); 41742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas ks.incrRefCountLPw(); 41842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas return ks; 41942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas } 420e2437126f0225135891544315ff72e54c7de0f59Yigit Boyar 421d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase // get the next keyset id 42242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas long id = getFreeKeySetIDLPw(); 42342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 42442e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas // create the KeySet object and add to mKeySets and mapping 425c587f7dba5a337169e854e235da59f595255d6ccAga Madurska KeySetHandle ks = new KeySetHandle(id); 42642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mKeySets.put(id, ks); 42742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mKeySetMapping.put(id, addedKeyIds); 42842e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas return ks; 42942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas } 43042e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 43142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas /* 43242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas * Decrements the reference to KeySet represented by the given id. If this 43342e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas * drops to zero, then also decrement the reference to each public key it 434c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * contains and remove the KeySet. 43542e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas */ 43642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas private void decrementKeySetLPw(long id) { 43742e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas KeySetHandle ks = mKeySets.get(id); 438c587f7dba5a337169e854e235da59f595255d6ccAga Madurska if (ks == null) { 439c587f7dba5a337169e854e235da59f595255d6ccAga Madurska /* nothing to do */ 440c587f7dba5a337169e854e235da59f595255d6ccAga Madurska return; 4418edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar } 44242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas if (ks.decrRefCountLPw() <= 0) { 4438edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar ArraySet<Long> pubKeys = mKeySetMapping.get(id); 4448edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar final int pkSize = pubKeys.size(); 4458edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar for (int i = 0; i < pkSize; i++) { 4468edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar decrementPublicKeyLPw(pubKeys.valueAt(i)); 4478edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar } 4488edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar mKeySets.delete(id); 4498edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar mKeySetMapping.delete(id); 450959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 451959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 452959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 453959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar /* 454959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar * Decrements the reference to PublicKey represented by the given id. If 455619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar * this drops to zero, then remove it. 456619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar */ 457619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar private void decrementPublicKeyLPw(long id) { 458959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar PublicKeyHandle pk = mPublicKeys.get(id); 459959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar if (pk == null) { 460959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar /* nothing to do */ 461959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar return; 4628a11e6829c522aa1efcc903afa4c01d337082eabChris Craik } 463959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar if (pk.decrRefCountLPw() <= 0) { 464959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar mPublicKeys.delete(id); 465959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 466959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 467959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 4688a11e6829c522aa1efcc903afa4c01d337082eabChris Craik /** 469959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar * Adds the given PublicKey to the system, deduping as it goes. 470959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar */ 471959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar private long addPublicKeyLPw(PublicKey key) { 47242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas Preconditions.checkNotNull(key, "Cannot add null public key!"); 473959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar long id = getIdForPublicKeyLPr(key); 474959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar if (id != PUBLIC_KEY_NOT_FOUND) { 475959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 476959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar /* We already know about this key, increment its ref count and ret */ 477959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar mPublicKeys.get(id).incrRefCountLPw(); 478959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar return id; 479959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 480959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar 481959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar /* if it's new find the first unoccupied slot in the public keys */ 482959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar id = getFreePublicKeyIdLPw(); 483959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar mPublicKeys.put(id, new PublicKeyHandle(id, key)); 484959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar return id; 485959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 48642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 4878edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar /** 4888edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs. 4898edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar * 4908edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar * Returns KEYSET_NOT_FOUND if there isn't one. 4918edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar */ 492de5f54783555fa2e778c4ed6760472a002b2589bYigit Boyar private long getIdFromKeyIdsLPr(Set<Long> publicKeyIds) { 493959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) { 4949c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri ArraySet<Long> value = mKeySetMapping.valueAt(keyMapIndex); 495959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar if (value.equals(publicKeyIds)) { 496959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar return mKeySetMapping.keyAt(keyMapIndex); 497619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar } 498619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar } 499619ac016831a5ad75c2e0921c9036b6f030a9e63Yigit Boyar return KEYSET_NOT_FOUND; 500959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar } 50142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas 502959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar /** 503959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND. 504959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar */ 505959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar private long getIdForPublicKeyLPr(PublicKey k) { 506959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar String encodedPublicKey = new String(k.getEncoded()); 507959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) { 508504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar PublicKey value = mPublicKeys.valueAt(publicKeyIndex).getKey(); 5098edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar String encodedExistingKey = new String(value.getEncoded()); 5108edcb0bdeaba6931f9d8154f0c81f57da7ddab2aYigit Boyar if (encodedPublicKey.equals(encodedExistingKey)) { 511ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu return mPublicKeys.keyAt(publicKeyIndex); 51242e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas } 513ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu } 514ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu return PUBLIC_KEY_NOT_FOUND; 515ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu } 516ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu 517ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu /** 518ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu * Gets an unused stable identifier for a KeySet. 519ef3e37fe088c7d8e614bbc4ed58d6c0d3fa807a1Dake Gu */ 5204bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar private long getFreeKeySetIDLPw() { 52142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas lastIssuedKeySetId += 1; 5224bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar return lastIssuedKeySetId; 5234bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar } 5244bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar 5254bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar /** 5264bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar * Same as above, but for public keys. 5274bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar */ 5284bcf88a56f3048a7ead6f423faa8fa08b95c5daeYigit Boyar private long getFreePublicKeyIdLPw() { 5293d37afbbf7bf547c1e1c541df9be9696da668884Yigit Boyar lastIssuedKeyId += 1; 530d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase return lastIssuedKeyId; 531115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar } 532178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar 533d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase /* 534d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * This package is being removed from the system, so we need to 535d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * remove its keyset and public key references, then remove its 536310e95e1c6dfe4f26ef594233e65e1ff83e0f1ffYigit Boyar * keyset data. 537d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 538504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar public void removeAppKeySetDataLPw(String packageName) { 539504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar 540504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar /* remove refs from common keysets and public keys */ 541178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar PackageSetting pkg = mPackages.get(packageName); 542178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar Preconditions.checkNotNull(pkg, "pkg name: " + packageName 543178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar + "does not have a corresponding entry in mPackages."); 544178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar long signingKeySetId = pkg.keySetData.getProperSigningKeySet(); 545178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar decrementKeySetLPw(signingKeySetId); 546178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases(); 547178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar for (int i = 0; i < definedKeySets.size(); i++) { 548178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar decrementKeySetLPw(definedKeySets.valueAt(i)); 549178c4e15a0ebb501d2bb4f3ac3176e4c44954954Yigit Boyar } 550504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar 551d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase /* remove from package */ 552da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar clearPackageKeySetDataLPw(pkg); 553da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar return; 554da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar } 555da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar 556da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar private void clearPackageKeySetDataLPw(PackageSetting pkg) { 557da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar pkg.keySetData.setProperSigningKeySet(PackageKeySetData.KEYSET_UNASSIGNED); 558da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar pkg.keySetData.removeAllDefinedKeySets(); 559da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar pkg.keySetData.removeAllUpgradeKeySets(); 560da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar return; 561da50fde358bd3ef2edb273b3bf0265cf5e84ec6bYigit Boyar } 5629c0ad7d5adfbe51d85adcbc056b6183095d8aaedKeyvan Amiri 563e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public String encodePublicKey(PublicKey k) throws IOException { 564f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes return new String(Base64.encode(k.getEncoded(), Base64.NO_WRAP)); 565f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes } 566e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 567e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar public void dumpLPr(PrintWriter pw, String packageName, 568d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase PackageManagerService.DumpState dumpState) { 569d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase boolean printedHeader = false; 570d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase for (ArrayMap.Entry<String, PackageSetting> e : mPackages.entrySet()) { 571d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase String keySetPackage = e.getKey(); 572d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (packageName != null && !packageName.equals(keySetPackage)) { 57366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar continue; 57466826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } 57566826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar if (!printedHeader) { 57666826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar if (dumpState.onTitlePrinted()) 57766826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar pw.println(); 57866826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar pw.println("Key Set Manager:"); 57966826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar printedHeader = true; 58066826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar } 58166826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar PackageSetting pkg = e.getValue(); 58266826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar pw.print(" ["); pw.print(keySetPackage); pw.println("]"); 58366826566020afc8d11f183cf3fe443ac0a022384Yigit Boyar if (pkg.keySetData != null) { 584629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar boolean printedLabel = false; 585629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar for (ArrayMap.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) { 586e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar if (!printedLabel) { 587e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar pw.print(" KeySets Aliases: "); 588e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar printedLabel = true; 589e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar } else { 590e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar pw.print(", "); 591e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar } 592e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar pw.print(entry.getKey()); 593e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar pw.print('='); 594e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar pw.print(Long.toString(entry.getValue())); 595e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar } 596e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar if (printedLabel) { 597e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar pw.println(""); 598e3b89d11cf08a0e9aaa8162757246f286c6df2f8Yigit Boyar } 599b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar printedLabel = false; 600b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (pkg.keySetData.isUsingDefinedKeySets()) { 601b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar ArrayMap<String, Long> definedKeySets = pkg.keySetData.getAliases(); 602b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar final int dksSize = definedKeySets.size(); 603b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar for (int i = 0; i < dksSize; i++) { 604b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar if (!printedLabel) { 605b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar pw.print(" Defined KeySets: "); 606b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar printedLabel = true; 607b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } else { 608b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar pw.print(", "); 609d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 610d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase pw.print(Long.toString(definedKeySets.valueAt(i))); 611d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 612d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 613d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (printedLabel) { 614d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase pw.println(""); 615d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 616d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase printedLabel = false; 617d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase final long signingKeySet = pkg.keySetData.getProperSigningKeySet(); 618d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase pw.print(" Signing KeySets: "); 619d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase pw.print(Long.toString(signingKeySet)); 620d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase pw.println(""); 621115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar if (pkg.keySetData.isUsingUpgradeKeySets()) { 622b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar for (long keySetId : pkg.keySetData.getUpgradeKeySets()) { 623d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (!printedLabel) { 624d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase pw.print(" Upgrade KeySets: "); 6258ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar printedLabel = true; 6268ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } else { 6278ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar pw.print(", "); 6288ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 6298ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar pw.print(Long.toString(keySetId)); 630d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 631d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 632d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase if (printedLabel) { 633b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar pw.println(""); 634b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 635b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 636b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar } 637e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 638fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar 639b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar void writeKeySetManagerServiceLPr(XmlSerializer serializer) throws IOException { 640d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase serializer.startTag(null, "keyset-settings"); 641d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase serializer.attribute(null, "version", Integer.toString(CURRENT_VERSION)); 6425ced882cabdcefbb469e332f6f73983999aad0e5Yigit Boyar writePublicKeysLPr(serializer); 643504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar writeKeySetsLPr(serializer); 6445ced882cabdcefbb469e332f6f73983999aad0e5Yigit Boyar serializer.startTag(null, "lastIssuedKeyId"); 645b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar serializer.attribute(null, "value", Long.toString(lastIssuedKeyId)); 646d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase serializer.endTag(null, "lastIssuedKeyId"); 647d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase serializer.startTag(null, "lastIssuedKeySetId"); 648d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId)); 649b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar serializer.endTag(null, "lastIssuedKeySetId"); 650b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar serializer.endTag(null, "keyset-settings"); 651c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar } 652c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar 653c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar void writePublicKeysLPr(XmlSerializer serializer) throws IOException { 654c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar serializer.startTag(null, "keys"); 655c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) { 656c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar long id = mPublicKeys.keyAt(pKeyIndex); 657c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar PublicKeyHandle pkh = mPublicKeys.valueAt(pKeyIndex); 658b5f8b4fecb531aee6b359b4968409410aba90817Yigit Boyar String encodedKey = encodePublicKey(pkh.getKey()); 6598da5bba529a2fe9bd2aafab28010e11ec4de93c7Yigit Boyar serializer.startTag(null, "public-key"); 6608da5bba529a2fe9bd2aafab28010e11ec4de93c7Yigit Boyar serializer.attribute(null, "identifier", Long.toString(id)); 661c8b0ff5869e17a656a3a1d7fb306efa5b99fa07fYigit Boyar serializer.attribute(null, "value", encodedKey); 662d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase serializer.endTag(null, "public-key"); 663e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 664e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar serializer.endTag(null, "keys"); 665e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 666e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 667e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar void writeKeySetsLPr(XmlSerializer serializer) throws IOException { 668e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar serializer.startTag(null, "keysets"); 669e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) { 670e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar long id = mKeySetMapping.keyAt(keySetIndex); 671504c54ea52c1b2aae6f8f4ae128f1dcaac7e3f6aYigit Boyar ArraySet<Long> keys = mKeySetMapping.valueAt(keySetIndex); 672d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase serializer.startTag(null, "keyset"); 673d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase serializer.attribute(null, "identifier", Long.toString(id)); 674fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar for (long keyId : keys) { 675fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar serializer.startTag(null, "key-id"); 676e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar serializer.attribute(null, "identifier", Long.toString(keyId)); 677e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar serializer.endTag(null, "key-id"); 678e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar } 679e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar serializer.endTag(null, "keyset"); 680e0c347f627f8a78d3e5e3e5eaac9c3ae26208689Yigit Boyar } 681fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar serializer.endTag(null, "keysets"); 682fe3996cf5af65fe11cc3ed47b67123ec267bd336Yigit Boyar } 683bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar 684bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar void readKeySetsLPw(XmlPullParser parser, ArrayMap<Long, Integer> keySetRefCounts) 685bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar throws XmlPullParserException, IOException { 686bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar int type; 687bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar long currentKeySetId = 0; 688bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar int outerDepth = parser.getDepth(); 689bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar String recordedVersionStr = parser.getAttributeValue(null, "version"); 690bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar if (recordedVersionStr == null) { 691bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar // The keyset information comes from pre-versioned devices, and 692bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar // is inaccurate, don't collect any of it. 693bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 694bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 695bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar continue; 696bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar } 697f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes // The KeySet information read previously from packages.xml is invalid. 698bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar // Destroy it all. 699bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar for (PackageSetting p : mPackages.values()) { 700bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar clearPackageKeySetDataLPw(p); 701bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar } 702bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar return; 703bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar } 704f129f1b050d2542a91fe8175eac30183beb07b41Chris Banes int recordedVersion = Integer.parseInt(recordedVersionStr); 705bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 706bb6ebab3b3b85ec20b3bc262289a2460705322f5Yigit Boyar && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 7079290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 7089290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar continue; 7099290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7109290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar final String tagName = parser.getName(); 7119290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar if (tagName.equals("keys")) { 7129290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar readKeysLPw(parser); 7139290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } else if (tagName.equals("keysets")) { 7149290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar readKeySetListLPw(parser); 7159290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } else if (tagName.equals("lastIssuedKeyId")) { 7169290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value")); 7179290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } else if (tagName.equals("lastIssuedKeySetId")) { 7189290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value")); 7199290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7209290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7219290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar 7229290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar addRefCountsFromSavedPackagesLPw(keySetRefCounts); 7239290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7249290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar 7259290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar void readKeysLPw(XmlPullParser parser) 7269290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar throws XmlPullParserException, IOException { 7279290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar int outerDepth = parser.getDepth(); 7289290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar int type; 7299290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 7309290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 7319290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 7329290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar continue; 7339290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7349290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar final String tagName = parser.getName(); 7359290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar if (tagName.equals("public-key")) { 7369290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar readPublicKeyLPw(parser); 7379290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7389290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7399290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7409290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar 7419290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar void readKeySetListLPw(XmlPullParser parser) 7429290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar throws XmlPullParserException, IOException { 7439290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar int outerDepth = parser.getDepth(); 7449290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar int type; 7459290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar long currentKeySetId = 0; 7469290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 7479290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { 7489290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { 7499290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar continue; 7509290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7519290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar final String tagName = parser.getName(); 7529290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar if (tagName.equals("keyset")) { 7539290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar String encodedID = parser.getAttributeValue(null, "identifier"); 7549290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar currentKeySetId = Long.parseLong(encodedID); 7559290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar int refCount = 0; 7569290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar mKeySets.put(currentKeySetId, new KeySetHandle(currentKeySetId, refCount)); 7579290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar mKeySetMapping.put(currentKeySetId, new ArraySet<Long>()); 7589290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } else if (tagName.equals("key-id")) { 7599290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar String encodedID = parser.getAttributeValue(null, "identifier"); 7609290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar long id = Long.parseLong(encodedID); 7619290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar mKeySetMapping.get(currentKeySetId).add(id); 7629290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 7639290baf2c13c27d6f6d517b198a3fc079b83f297Yigit Boyar } 764d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase } 765d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase 766d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase void readPublicKeyLPw(XmlPullParser parser) 76711b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar throws XmlPullParserException { 76811b7cfea15306c0d6e4ed7da09f7698df01695dfYigit Boyar String encodedID = parser.getAttributeValue(null, "identifier"); 769d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase long identifier = Long.parseLong(encodedID); 7702d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar int refCount = 0; 771d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase String encodedPublicKey = parser.getAttributeValue(null, "value"); 7729eeb624e8d3a9e7dc4e70eec759ab60104aab459Dake Gu PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey); 7739051a368c00c40f8679ae67147b9f5af6f93638dYigit Boyar if (pub != null) { 77465dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri PublicKeyHandle pkh = new PublicKeyHandle(identifier, refCount, pub); 775d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase mPublicKeys.put(identifier, pkh); 7762d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar } 7772d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar } 7782d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar 77965dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri /* 78065dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri * Set each KeySet ref count. Also increment all public keys in each keyset. 78165dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri */ 78265dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri private void addRefCountsFromSavedPackagesLPw(ArrayMap<Long, Integer> keySetRefCounts) { 78365dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri final int numRefCounts = keySetRefCounts.size(); 78465dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri for (int i = 0; i < numRefCounts; i++) { 78565dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri KeySetHandle ks = mKeySets.get(keySetRefCounts.keyAt(i)); 78665dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri if (ks == null) { 78765dea0f8960efe2487c05abeeccb92689bab1332Keyvan Amiri /* something went terribly wrong and we have references to a non-existent key-set */ 788d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase Slog.wtf(TAG, "Encountered non-existent key-set reference when reading settings"); 7898ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar continue; 7908ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 7918ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar ks.setRefCountLPw(keySetRefCounts.valueAt(i)); 7928ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar } 7938ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar 7942d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar /* 7952d2e8d88103866b631eb0f3805da137ebcfb0275Yigit Boyar * In case something went terribly wrong and we have keysets with no associated packges 7968ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar * that refer to them, record the orphaned keyset ids, and remove them using 7978ae76f91527ce850f155ce960fb9068bcd5d49f9Yigit Boyar * decrementKeySetLPw() after all keyset references have been set so that the associtaed 798d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase * public keys have the appropriate references from all keysets. 799d7d27e9ebe5c7325e67e1a8af265378bd2056cadChet Haase */ 800046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard ArraySet<Long> orphanedKeySets = new ArraySet<Long>(); 801151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri final int numKeySets = mKeySets.size(); 802046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard for (int i = 0; i < numKeySets; i++) { 803046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard if (mKeySets.valueAt(i).getRefCountLPr() == 0) { 804046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard Slog.wtf(TAG, "Encountered key-set w/out package references when reading settings"); 805046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard orphanedKeySets.add(mKeySets.keyAt(i)); 806151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri } 807151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri ArraySet<Long> pubKeys = mKeySetMapping.valueAt(i); 808151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri final int pkSize = pubKeys.size(); 8098a11e6829c522aa1efcc903afa4c01d337082eabChris Craik for (int j = 0; j < pkSize; j++) { 810046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard mPublicKeys.get(pubKeys.valueAt(j)).incrRefCountLPw(); 811046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard } 812151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri } 813046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard final int numOrphans = orphanedKeySets.size(); 814046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard for (int i = 0; i < numOrphans; i++) { 815046a8a022958d8d21c32ad424e07d592fe87a8bdshepshapard decrementKeySetLPw(orphanedKeySets.valueAt(i)); 816151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri } 817151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri } 818151e43e7057619d714bc0f91ac7e2139ee334058Keyvan Amiri} 8198a11e6829c522aa1efcc903afa4c01d337082eabChris Craik