1f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra/*
2f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * Copyright (C) 2013 The Android Open Source Project
3f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra *
4f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * Licensed under the Apache License, Version 2.0 (the "License");
5f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * you may not use this file except in compliance with the License.
6f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * You may obtain a copy of the License at
7f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra *
8f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra *      http://www.apache.org/licenses/LICENSE-2.0
9f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra *
10f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * Unless required by applicable law or agreed to in writing, software
11f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * distributed under the License is distributed on an "AS IS" BASIS,
12f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * See the License for the specific language governing permissions and
14f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * limitations under the License.
15f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra */
16f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
17f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condrapackage com.android.server.pm;
18f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
19f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport android.content.pm.KeySet;
20f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport android.content.pm.PackageParser;
21f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport android.os.Binder;
22f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport android.util.Base64;
23f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport android.util.Log;
24f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport android.util.LongSparseArray;
25f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
26f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport java.io.IOException;
27f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport java.io.PrintWriter;
28f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport java.security.PublicKey;
29f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport java.util.HashMap;
30f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport java.util.HashSet;
31f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport java.util.Map;
32f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport java.util.Set;
33f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
34f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport org.xmlpull.v1.XmlPullParser;
35f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport org.xmlpull.v1.XmlPullParserException;
36f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condraimport org.xmlpull.v1.XmlSerializer;
37f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
38f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra/*
39f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra * Manages system-wide KeySet state.
40f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra */
41f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condrapublic class KeySetManager {
42f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
43f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    static final String TAG = "KeySetManager";
44f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
459a995f57a3cbfefc248498bbd51e7a09f584ff4fKenny Root    /** Sentinel value returned when a {@code KeySet} is not found. */
469a995f57a3cbfefc248498bbd51e7a09f584ff4fKenny Root    public static final long KEYSET_NOT_FOUND = -1;
479a995f57a3cbfefc248498bbd51e7a09f584ff4fKenny Root
489a995f57a3cbfefc248498bbd51e7a09f584ff4fKenny Root    /** Sentinel value returned when public key is not found. */
49f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private static final long PUBLIC_KEY_NOT_FOUND = -1;
50f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
51f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private final Object mLockObject = new Object();
52f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
53f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private final LongSparseArray<KeySet> mKeySets;
54f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
55f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private final LongSparseArray<PublicKey> mPublicKeys;
56f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
57f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private final LongSparseArray<Set<Long>> mKeySetMapping;
58f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
59f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private final Map<String, PackageSetting> mPackages;
60f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
61f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private static long lastIssuedKeySetId = 0;
62f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
63f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private static long lastIssuedKeyId = 0;
64f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
65f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public KeySetManager(Map<String, PackageSetting> packages) {
66f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        mKeySets = new LongSparseArray<KeySet>();
67f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        mPublicKeys = new LongSparseArray<PublicKey>();
68f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        mKeySetMapping = new LongSparseArray<Set<Long>>();
69f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        mPackages = packages;
70f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
71f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
722042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
73f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Determine if a package is signed by the given KeySet.
74f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
75f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Returns false if the package was not signed by all the
76f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * keys in the KeySet.
77f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
78f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Returns true if the package was signed by at least the
79f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * keys in the given KeySet.
80f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
81f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Note that this can return true for multiple KeySets.
82f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
83f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public boolean packageIsSignedBy(String packageName, KeySet ks) {
84f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
85f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            PackageSetting pkg = mPackages.get(packageName);
86f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (pkg == null) {
87f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new NullPointerException("Invalid package name");
88f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
89f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (pkg.keySetData == null) {
90f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new NullPointerException("Package has no KeySet data");
91f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
92f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            long id = getIdByKeySetLocked(ks);
93f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return pkg.keySetData.packageIsSignedBy(id);
94f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
95f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
96f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
972042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
98f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * This informs the system that the given package has defined a KeySet
99f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * in its manifest that a) contains the given keys and b) is named
100f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * alias by that package.
101f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
102f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public void addDefinedKeySetToPackage(String packageName,
103f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            Set<PublicKey> keys, String alias) {
104f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        if ((packageName == null) || (keys == null) || (alias == null)) {
105c30d92e2241ad329ceb67e216e1e5adfbfc84d99Dianne Hackborn            //Log.d(TAG, "Got null argument for a defined keyset, ignoring!");
106f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return;
107f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
108f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
109f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            KeySet ks = addKeySetLocked(keys);
110f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            PackageSetting pkg = mPackages.get(packageName);
111f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (pkg == null) {
112f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new NullPointerException("Unknown package");
113f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
114f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            long id = getIdByKeySetLocked(ks);
115f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            pkg.keySetData.addDefinedKeySet(id, alias);
116f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
117f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
118f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
1192042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
120f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Similar to the above, this informs the system that the given package
121f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * was signed by the provided KeySet.
122f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
123f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public void addSigningKeySetToPackage(String packageName,
124f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            Set<PublicKey> signingKeys) {
125f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        if ((packageName == null) || (signingKeys == null)) {
126c30d92e2241ad329ceb67e216e1e5adfbfc84d99Dianne Hackborn            //Log.d(TAG, "Got null argument for a signing keyset, ignoring!");
127f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return;
128f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
129f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
130f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            // add the signing KeySet
131f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            KeySet ks = addKeySetLocked(signingKeys);
132f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            long id = getIdByKeySetLocked(ks);
133f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            Set<Long> publicKeyIds = mKeySetMapping.get(id);
134f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (publicKeyIds == null) {
135f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new NullPointerException("Got invalid KeySet id");
136f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
137f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
138f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            // attach it to the package
139f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            PackageSetting pkg = mPackages.get(packageName);
140f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (pkg == null) {
141f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new NullPointerException("No such package!");
142f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
143f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            pkg.keySetData.addSigningKeySet(id);
144f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
145f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            // for each KeySet the package defines which is a subset of
146f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            // the one above, add the KeySet id to the package's signing KeySets
147f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            for (Long keySetID : pkg.keySetData.getDefinedKeySets()) {
148f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                Set<Long> definedKeys = mKeySetMapping.get(keySetID);
149f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                if (publicKeyIds.contains(definedKeys)) {
150f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                    pkg.keySetData.addSigningKeySet(keySetID);
151f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                }
152f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
153f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
154f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
155f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
1562042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
1572042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * Fetches the stable identifier associated with the given KeySet. Returns
1582042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * {@link #KEYSET_NOT_FOUND} if the KeySet... wasn't found.
159f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
160f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public long getIdByKeySet(KeySet ks) {
161f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
162f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return getIdByKeySetLocked(ks);
163f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
164f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
165f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
166f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private long getIdByKeySetLocked(KeySet ks) {
167f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        for (int keySetIndex = 0; keySetIndex < mKeySets.size(); keySetIndex++) {
168f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            KeySet value = mKeySets.valueAt(keySetIndex);
169f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (ks.equals(value)) {
170f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                return mKeySets.keyAt(keySetIndex);
171f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
172f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
173f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return KEYSET_NOT_FOUND;
174f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
175f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
1762042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
177f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Fetches the KeySet corresponding to the given stable identifier.
178f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
1792042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * Returns {@link #KEYSET_NOT_FOUND} if the identifier doesn't
1802042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * identify a {@link KeySet}.
181f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
182f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public KeySet getKeySetById(long id) {
183f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
184f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return mKeySets.get(id);
185f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
186f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
187f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
1882042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
189f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Fetches the KeySet that a given package refers to by the provided alias.
190f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
191f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * If the package isn't known to us, throws an IllegalArgumentException.
192f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Returns null if the alias isn't known to us.
193f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
194f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public KeySet getKeySetByAliasAndPackageName(String packageName, String alias) {
195f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
196f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            PackageSetting p = mPackages.get(packageName);
197f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (p == null) {
198f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new NullPointerException("Unknown package");
199f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
200f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (p.keySetData == null) {
201f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new IllegalArgumentException("Package has no keySet data");
202f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
203f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            long keySetId = p.keySetData.getAliases().get(alias);
204f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return mKeySets.get(keySetId);
205f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
206f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
207f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
2082042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
2092042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * Fetches all the known {@link KeySet KeySets} that signed the given
2102042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * package. Returns {@code null} if package is unknown.
211f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
212f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public Set<KeySet> getSigningKeySetsByPackageName(String packageName) {
213f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
214f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            Set<KeySet> signingKeySets = new HashSet<KeySet>();
215f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            PackageSetting p = mPackages.get(packageName);
216f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (p == null) {
217f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new NullPointerException("Unknown package");
218f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
219f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (p.keySetData == null) {
220f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                throw new IllegalArgumentException("Package has no keySet data");
221f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
222f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            for (long l : p.keySetData.getSigningKeySets()) {
223f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                signingKeySets.add(mKeySets.get(l));
224f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
225f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return signingKeySets;
226f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
227f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
228f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
2292042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
230f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Creates a new KeySet corresponding to the given keys.
231f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
2322042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * If the {@link PublicKey PublicKeys} aren't known to the system, this
2332042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * adds them. Otherwise, they're deduped.
234f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
235f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * If the KeySet isn't known to the system, this adds that and creates the
236f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * mapping to the PublicKeys. If it is known, then it's deduped.
237f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
2382042e9df4855ef59e3329b548b208279a88d7adbKenny Root     * Throws if the provided set is {@code null}.
239f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
240f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private KeySet addKeySetLocked(Set<PublicKey> keys) {
241f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        if (keys == null) {
242f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            throw new NullPointerException("Provided keys cannot be null");
243f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
244f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // add each of the keys in the provided set
245f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        Set<Long> addedKeyIds = new HashSet<Long>(keys.size());
246f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        for (PublicKey k : keys) {
247f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            long id = addPublicKeyLocked(k);
248f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            addedKeyIds.add(id);
249f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
250f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
251f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // check to see if the resulting keyset is new
252f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        long existingKeySetId = getIdFromKeyIdsLocked(addedKeyIds);
253f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        if (existingKeySetId != KEYSET_NOT_FOUND) {
254f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return mKeySets.get(existingKeySetId);
255f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
256f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
257f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // create the KeySet object
258f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        KeySet ks = new KeySet(new Binder());
259f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // get the first unoccupied slot in mKeySets
260f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        long id = getFreeKeySetIDLocked();
261f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // add the KeySet object to it
262f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        mKeySets.put(id, ks);
263f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // add the stable key ids to the mapping
264f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        mKeySetMapping.put(id, addedKeyIds);
265f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // go home
266f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return ks;
267f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
268f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
2692042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
270f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Adds the given PublicKey to the system, deduping as it goes.
271f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
272f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private long addPublicKeyLocked(PublicKey key) {
273f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // check if the public key is new
274f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        long existingKeyId = getIdForPublicKeyLocked(key);
275f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        if (existingKeyId != PUBLIC_KEY_NOT_FOUND) {
276f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            return existingKeyId;
277f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
278f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // if it's new find the first unoccupied slot in the public keys
279f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        long id = getFreePublicKeyIdLocked();
280f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // add the public key to it
281f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        mPublicKeys.put(id, key);
282f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        // return the stable identifier
283f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return id;
284f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
285f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
2862042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
287f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Finds the stable identifier for a KeySet based on a set of PublicKey stable IDs.
288f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     *
289f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Returns KEYSET_NOT_FOUND if there isn't one.
290f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
291f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private long getIdFromKeyIdsLocked(Set<Long> publicKeyIds) {
292f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        for (int keyMapIndex = 0; keyMapIndex < mKeySetMapping.size(); keyMapIndex++) {
293f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            Set<Long> value = mKeySetMapping.valueAt(keyMapIndex);
294f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (value.equals(publicKeyIds)) {
295f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                return mKeySetMapping.keyAt(keyMapIndex);
296f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
297f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
298f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return KEYSET_NOT_FOUND;
299f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
300f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
3012042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
302f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Finds the stable identifier for a PublicKey or PUBLIC_KEY_NOT_FOUND.
303f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
304f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private long getIdForPublicKeyLocked(PublicKey k) {
305f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        String encodedPublicKey = new String(k.getEncoded());
306f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        for (int publicKeyIndex = 0; publicKeyIndex < mPublicKeys.size(); publicKeyIndex++) {
307f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            PublicKey value = mPublicKeys.valueAt(publicKeyIndex);
308f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            String encodedExistingKey = new String(value.getEncoded());
309f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (encodedPublicKey.equals(encodedExistingKey)) {
310f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                return mPublicKeys.keyAt(publicKeyIndex);
311f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
312f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
313f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return PUBLIC_KEY_NOT_FOUND;
314f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
315f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
3162042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
317f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Gets an unused stable identifier for a KeySet.
318f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
319f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private long getFreeKeySetIDLocked() {
320f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        lastIssuedKeySetId += 1;
321f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return lastIssuedKeySetId;
322f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
323f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
3242042e9df4855ef59e3329b548b208279a88d7adbKenny Root    /**
325f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     * Same as above, but for public keys.
326f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra     */
327f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    private long getFreePublicKeyIdLocked() {
328f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        lastIssuedKeyId += 1;
329f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return lastIssuedKeyId;
330f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
331f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
332f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public void removeAppKeySetData(String packageName) {
333f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
334f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            // Get the package's known keys and KeySets
335cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra            Set<Long> deletableKeySets = getKnownKeySetsByPackageNameLocked(packageName);
336f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            Set<Long> deletableKeys = new HashSet<Long>();
337cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra            Set<Long> knownKeys = null;
338f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            for (Long ks : deletableKeySets) {
339cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                knownKeys = mKeySetMapping.get(ks);
340cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                if (knownKeys != null) {
341cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                    deletableKeys.addAll(knownKeys);
342cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                }
343f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
344f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
345f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            // Now remove the keys and KeySets known to any other package
346f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            for (String pkgName : mPackages.keySet()) {
347f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                if (pkgName.equals(packageName)) {
348f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                    continue;
349f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                }
350cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                Set<Long> knownKeySets = getKnownKeySetsByPackageNameLocked(pkgName);
351f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                deletableKeySets.removeAll(knownKeySets);
352cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                knownKeys = new HashSet<Long>();
353f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                for (Long ks : knownKeySets) {
354cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                    knownKeys = mKeySetMapping.get(ks);
355cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                    if (knownKeys != null) {
356cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                        deletableKeys.removeAll(knownKeys);
357cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                    }
358f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                }
359f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
360f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
361f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            // The remaining keys and KeySets are not known to any other
362f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            // application and so can be safely deleted.
363f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            for (Long ks : deletableKeySets) {
364f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                mKeySets.delete(ks);
365f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                mKeySetMapping.delete(ks);
366f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
367f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            for (Long keyId : deletableKeys) {
368f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                mPublicKeys.delete(keyId);
369f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
370cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra
371cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra            // Now remove them from the KeySets known to each package
372cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra            for (String pkgName : mPackages.keySet()) {
37392179bc261cf9ff216f10a9adf64088ed76675cbKenny Root                PackageSetting p = mPackages.get(pkgName);
374cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                for (Long ks : deletableKeySets) {
375cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                    p.keySetData.removeSigningKeySet(ks);
376cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                    p.keySetData.removeDefinedKeySet(ks);
377cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra                }
378cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra            }
379f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
380f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
381f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
382cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra    private Set<Long> getKnownKeySetsByPackageNameLocked(String packageName) {
383f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        PackageSetting p = mPackages.get(packageName);
384f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        if (p == null) {
385f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            throw new NullPointerException("Unknown package");
386f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
387f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        if (p.keySetData == null) {
388f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            throw new IllegalArgumentException("Package has no keySet data");
389f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
390f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        Set<Long> knownKeySets = new HashSet<Long>();
391cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra        for (long ks : p.keySetData.getSigningKeySets()) {
392f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            knownKeySets.add(ks);
393f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
394cdb5789022791f5557e4915f9be4dc5e6dd8b46eGeremy Condra        for (long ks : p.keySetData.getDefinedKeySets()) {
395f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            knownKeySets.add(ks);
396f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
397f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return knownKeySets;
398f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
399f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
400f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    public String encodePublicKey(PublicKey k) throws IOException {
401f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return new String(Base64.encode(k.getEncoded(), 0));
402f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
403f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
404cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn    public void dump(PrintWriter pw, String packageName,
405cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn            PackageManagerService.DumpState dumpState) {
406f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        synchronized (mLockObject) {
407cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn            boolean printedHeader = false;
408f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            for (Map.Entry<String, PackageSetting> e : mPackages.entrySet()) {
409cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                String keySetPackage = e.getKey();
410cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                if (packageName != null && !packageName.equals(keySetPackage)) {
411cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    continue;
412cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                }
413cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                if (!printedHeader) {
414cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    if (dumpState.onTitlePrinted())
415cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        pw.println();
416cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    pw.println("Key Set Manager:");
417cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    printedHeader = true;
418cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                }
419f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                PackageSetting pkg = e.getValue();
420cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                pw.print("  ["); pw.print(keySetPackage); pw.println("]");
421f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                if (pkg.keySetData != null) {
422cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    boolean printedLabel = false;
423fb236b56d23fa563880f98ec3fc484723235296cYing Wang                    for (Map.Entry<String, Long> entry : pkg.keySetData.getAliases().entrySet()) {
424df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                        if (!printedLabel) {
425df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                            pw.print("      KeySets Aliases: ");
426df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                            printedLabel = true;
427df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                        } else {
428df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                            pw.print(", ");
429df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                        }
430df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                        pw.print(entry.getKey());
431df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                        pw.print('=');
432df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                        pw.print(Long.toString(entry.getValue()));
433df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                    }
434df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                    if (printedLabel) {
435df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                        pw.println("");
436df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                    }
437df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                    printedLabel = false;
438f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                    for (long keySetId : pkg.keySetData.getDefinedKeySets()) {
439cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        if (!printedLabel) {
440cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                            pw.print("      Defined KeySets: ");
441cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                            printedLabel = true;
442cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        } else {
443cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                            pw.print(", ");
444cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        }
445cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        pw.print(Long.toString(keySetId));
446cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    }
447cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    if (printedLabel) {
448cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        pw.println("");
449f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                    }
450cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    printedLabel = false;
451f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                    for (long keySetId : pkg.keySetData.getSigningKeySets()) {
452cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        if (!printedLabel) {
453df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                            pw.print("      Signing KeySets: ");
454cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                            printedLabel = true;
455cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        } else {
456cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                            pw.print(", ");
457cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        }
458df0e6abd9f5863740942a1da12685f261016a8e1Kenny Root                        pw.print(Long.toString(keySetId));
459f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                    }
460cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    if (printedLabel) {
461cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                        pw.println("");
462cbfd23ee6f14445c3e17c5169abbc80c216fa137Dianne Hackborn                    }
463f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                }
464f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
465f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
466f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
467f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
468f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    void writeKeySetManagerLPr(XmlSerializer serializer) throws IOException {
469f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.startTag(null, "keyset-settings");
470f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        writePublicKeysLPr(serializer);
471f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        writeKeySetsLPr(serializer);
472f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.startTag(null, "lastIssuedKeyId");
473f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.attribute(null, "value", Long.toString(lastIssuedKeyId));
474f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.endTag(null, "lastIssuedKeyId");
475f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.startTag(null, "lastIssuedKeySetId");
476f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.attribute(null, "value", Long.toString(lastIssuedKeySetId));
477f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.endTag(null, "lastIssuedKeySetId");
478f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.endTag(null, "keyset-settings");
479f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
480f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
481f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    void writePublicKeysLPr(XmlSerializer serializer) throws IOException {
482f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.startTag(null, "keys");
483f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        for (int pKeyIndex = 0; pKeyIndex < mPublicKeys.size(); pKeyIndex++) {
484f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            long id = mPublicKeys.keyAt(pKeyIndex);
485f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            PublicKey key = mPublicKeys.valueAt(pKeyIndex);
486f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            String encodedKey = encodePublicKey(key);
487f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            serializer.startTag(null, "public-key");
488f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            serializer.attribute(null, "identifier", Long.toString(id));
489f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            serializer.attribute(null, "value", encodedKey);
490f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            serializer.endTag(null, "public-key");
491f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
492f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.endTag(null, "keys");
493f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
494f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
495f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    void writeKeySetsLPr(XmlSerializer serializer) throws IOException {
496f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.startTag(null, "keysets");
497f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        for (int keySetIndex = 0; keySetIndex < mKeySetMapping.size(); keySetIndex++) {
498f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            long id = mKeySetMapping.keyAt(keySetIndex);
499f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            Set<Long> keys = mKeySetMapping.valueAt(keySetIndex);
500f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            serializer.startTag(null, "keyset");
501f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            serializer.attribute(null, "identifier", Long.toString(id));
502f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            for (long keyId : keys) {
503f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                serializer.startTag(null, "key-id");
504f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                serializer.attribute(null, "identifier", Long.toString(keyId));
505f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                serializer.endTag(null, "key-id");
506f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
507f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            serializer.endTag(null, "keyset");
508f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
509f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        serializer.endTag(null, "keysets");
510f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
511f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
512f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    void readKeySetsLPw(XmlPullParser parser)
513f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            throws XmlPullParserException, IOException {
514f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        int type;
515f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        long currentKeySetId = 0;
516f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
517f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
518f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                continue;
519f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
520f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            final String tagName = parser.getName();
521f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (tagName.equals("keys")) {
522f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                readKeysLPw(parser);
523f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            } else if (tagName.equals("keysets")) {
524f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                readKeySetListLPw(parser);
525f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
526f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
527f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
528f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
529f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    void readKeysLPw(XmlPullParser parser)
530f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            throws XmlPullParserException, IOException {
531f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        int outerDepth = parser.getDepth();
532f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        int type;
533f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
534f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
535f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
536f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                continue;
537f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
538f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            final String tagName = parser.getName();
539f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (tagName.equals("public-key")) {
540f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                readPublicKeyLPw(parser);
541f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            } else if (tagName.equals("lastIssuedKeyId")) {
542f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                lastIssuedKeyId = Long.parseLong(parser.getAttributeValue(null, "value"));
543f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            } else if (tagName.equals("lastIssuedKeySetId")) {
544f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                lastIssuedKeySetId = Long.parseLong(parser.getAttributeValue(null, "value"));
545f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
546f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
547f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
548f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
549f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    void readKeySetListLPw(XmlPullParser parser)
550f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            throws XmlPullParserException, IOException {
551f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        int outerDepth = parser.getDepth();
552f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        int type;
553f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        long currentKeySetId = 0;
554f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
555f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
556f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
557f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                continue;
558f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
559f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            final String tagName = parser.getName();
560f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            if (tagName.equals("keyset")) {
561f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                currentKeySetId = readIdentifierLPw(parser);
562f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                mKeySets.put(currentKeySetId, new KeySet(new Binder()));
563f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                mKeySetMapping.put(currentKeySetId, new HashSet<Long>());
564f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            } else if (tagName.equals("key-id")) {
565f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                long id = readIdentifierLPw(parser);
566f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra                mKeySetMapping.get(currentKeySetId).add(id);
567f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            }
568f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
569f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
570f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
571f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    long readIdentifierLPw(XmlPullParser parser)
572f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            throws XmlPullParserException {
573f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        return Long.parseLong(parser.getAttributeValue(null, "identifier"));
574f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
575f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra
576f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    void readPublicKeyLPw(XmlPullParser parser)
577f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            throws XmlPullParserException {
578f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        String encodedID = parser.getAttributeValue(null, "identifier");
579f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        long identifier = Long.parseLong(encodedID);
580f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        String encodedPublicKey = parser.getAttributeValue(null, "value");
581f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        PublicKey pub = PackageParser.parsePublicKey(encodedPublicKey);
582a2d8eae2892e215a63ec5a1261e53a8a6a57d397Geremy Condra        if (pub != null) {
583f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra            mPublicKeys.put(identifier, pub);
584f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra        }
585f1bcca82158c39da3c3696f9af954be2c0be1809Geremy Condra    }
586fb236b56d23fa563880f98ec3fc484723235296cYing Wang}
587