1cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root/*
2cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Copyright (C) 2011 The Android Open Source Project
3cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root *
4cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * you may not use this file except in compliance with the License.
6cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * You may obtain a copy of the License at
7cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root *
8cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root *
10cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Unless required by applicable law or agreed to in writing, software
11cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * See the License for the specific language governing permissions and
14cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * limitations under the License.
15cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root */
16cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
17cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootpackage com.android.server.pm;
18cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
19cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport com.android.internal.util.XmlUtils;
20cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
21cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport org.xmlpull.v1.XmlPullParser;
22cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport org.xmlpull.v1.XmlPullParserException;
23cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport org.xmlpull.v1.XmlSerializer;
24cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
2577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashmanimport android.annotation.NonNull;
26420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumannimport android.content.pm.PackageParser;
27420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumannimport android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
28cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport android.content.pm.Signature;
29cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport android.util.Log;
30cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
31cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport java.io.IOException;
3277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashmanimport java.security.cert.CertificateException;
33cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport java.util.ArrayList;
34cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
35cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootclass PackageSignatures {
3677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
3777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman    @NonNull PackageParser.SigningDetails mSigningDetails;
38cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
39cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    PackageSignatures(PackageSignatures orig) {
4077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        if (orig != null && orig.mSigningDetails != PackageParser.SigningDetails.UNKNOWN) {
4177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            mSigningDetails = new PackageParser.SigningDetails(orig.mSigningDetails);
4277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        } else {
4377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
44cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
45cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
46cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
47420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann    PackageSignatures(PackageParser.SigningDetails signingDetails) {
4877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        mSigningDetails = signingDetails;
49cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
50cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
51cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    PackageSignatures() {
5277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
53cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
54cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
55cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    void writeXml(XmlSerializer serializer, String tagName,
5677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            ArrayList<Signature> writtenSignatures) throws IOException {
5777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        if (mSigningDetails.signatures == null) {
58cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            return;
59cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
60cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        serializer.startTag(null, tagName);
6177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        serializer.attribute(null, "count", Integer.toString(mSigningDetails.signatures.length));
6277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        serializer.attribute(null, "schemeVersion",
6377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                Integer.toString(mSigningDetails.signatureSchemeVersion));
6477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        writeCertsListXml(serializer, writtenSignatures, mSigningDetails.signatures, null);
6577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
6677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        // if we have past signer certificate information, write it out
6777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        if (mSigningDetails.pastSigningCertificates != null) {
6877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            serializer.startTag(null, "pastSigs");
6977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            serializer.attribute(null, "count",
7077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    Integer.toString(mSigningDetails.pastSigningCertificates.length));
7177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            writeCertsListXml(
7277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    serializer, writtenSignatures, mSigningDetails.pastSigningCertificates,
7377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    mSigningDetails.pastSigningCertificatesFlags);
7477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            serializer.endTag(null, "pastSigs");
7577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        }
7677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        serializer.endTag(null, tagName);
7777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman    }
7877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
7977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman    private void writeCertsListXml(XmlSerializer serializer, ArrayList<Signature> writtenSignatures,
8077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            Signature[] signatures, int[] flags) throws IOException {
8177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        for (int i=0; i<signatures.length; i++) {
82cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            serializer.startTag(null, "cert");
8377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            final Signature sig = signatures[i];
84cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            final int sigHash = sig.hashCode();
8577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            final int numWritten = writtenSignatures.size();
86cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            int j;
8777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            for (j=0; j<numWritten; j++) {
8877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                Signature writtenSig = writtenSignatures.get(j);
8977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                if (writtenSig.hashCode() == sigHash && writtenSig.equals(sig)) {
90cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    serializer.attribute(null, "index", Integer.toString(j));
91cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    break;
92cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                }
93cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            }
9477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            if (j >= numWritten) {
9577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                writtenSignatures.add(sig);
9677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                serializer.attribute(null, "index", Integer.toString(numWritten));
97cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                serializer.attribute(null, "key", sig.toCharsString());
98cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            }
9977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            if (flags != null) {
10077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                serializer.attribute(null, "flags", Integer.toString(flags[i]));
10177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            }
102cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            serializer.endTag(null, "cert");
103cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
104cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
105cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
10677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman    void readXml(XmlPullParser parser, ArrayList<Signature> readSignatures)
107cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            throws IOException, XmlPullParserException {
10877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        PackageParser.SigningDetails.Builder builder =
10977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                new PackageParser.SigningDetails.Builder();
11077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
111cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        String countStr = parser.getAttributeValue(null, "count");
112cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        if (countStr == null) {
113cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            PackageManagerService.reportSettingsProblem(Log.WARN,
11477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    "Error in package manager settings: <sigs> has"
115cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                       + " no count at " + parser.getPositionDescription());
116cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            XmlUtils.skipCurrentTag(parser);
117cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
11877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        final int count = Integer.parseInt(countStr);
11977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
120420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann        String schemeVersionStr = parser.getAttributeValue(null, "schemeVersion");
12177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        int signatureSchemeVersion;
122420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann        if (schemeVersionStr == null) {
123420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann            PackageManagerService.reportSettingsProblem(Log.WARN,
12477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    "Error in package manager settings: <sigs> has no schemeVersion at "
125420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann                        + parser.getPositionDescription());
12677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
127420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann        } else {
12877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            signatureSchemeVersion = Integer.parseInt(schemeVersionStr);
129420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann        }
13077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        builder.setSignatureSchemeVersion(signatureSchemeVersion);
13177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        Signature[] signatures = new Signature[count];
13277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        int pos = readCertsListXml(parser, readSignatures, signatures, null, builder);
13377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        builder.setSignatures(signatures);
13477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        if (pos < count) {
13577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            // Should never happen -- there is an error in the written
13677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            // settings -- but if it does we don't want to generate
13777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            // a bad array.
13877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            Signature[] newSigs = new Signature[pos];
13977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            System.arraycopy(signatures, 0, newSigs, 0, pos);
14077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            builder = builder.setSignatures(newSigs);
14177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            PackageManagerService.reportSettingsProblem(Log.WARN,
14277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    "Error in package manager settings: <sigs> count does not match number of "
14377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            + " <cert> entries" + parser.getPositionDescription());
14477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        }
14577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
14677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        try {
14777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            mSigningDetails = builder.build();
14877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        } catch (CertificateException e) {
14977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            PackageManagerService.reportSettingsProblem(Log.WARN,
15077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    "Error in package manager settings: <sigs> "
15177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            + "unable to convert certificate(s) to public key(s).");
15277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
15377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        }
15477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman    }
15577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
15677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman    private int readCertsListXml(XmlPullParser parser, ArrayList<Signature> readSignatures,
15777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            Signature[] signatures, int[] flags, PackageParser.SigningDetails.Builder builder)
15877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            throws IOException, XmlPullParserException {
15977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        int count = signatures.length;
160cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        int pos = 0;
161cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
162cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        int outerDepth = parser.getDepth();
163cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        int type;
164cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
16577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                && (type != XmlPullParser.END_TAG
16677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                || parser.getDepth() > outerDepth)) {
167cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            if (type == XmlPullParser.END_TAG
168cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    || type == XmlPullParser.TEXT) {
169cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                continue;
170cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            }
171cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
172cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            String tagName = parser.getName();
173cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            if (tagName.equals("cert")) {
174cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                if (pos < count) {
175cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    String index = parser.getAttributeValue(null, "index");
176cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    if (index != null) {
177cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                        try {
178cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                            int idx = Integer.parseInt(index);
179cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                            String key = parser.getAttributeValue(null, "key");
180cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                            if (key == null) {
18177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                if (idx >= 0 && idx < readSignatures.size()) {
18277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    Signature sig = readSignatures.get(idx);
183cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                    if (sig != null) {
18477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                        signatures[pos] = readSignatures.get(idx);
185cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                    } else {
186cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                        PackageManagerService.reportSettingsProblem(Log.WARN,
187cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                                "Error in package manager settings: <cert> "
18877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                                        + "index " + index + " is not defined at "
18977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                                        + parser.getPositionDescription());
190cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                    }
191cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                } else {
192cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                    PackageManagerService.reportSettingsProblem(Log.WARN,
193cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                            "Error in package manager settings: <cert> "
19477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                                    + "index " + index + " is out of bounds at "
19577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                                    + parser.getPositionDescription());
196cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                }
197cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                            } else {
19877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                while (readSignatures.size() <= idx) {
19977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    readSignatures.add(null);
200cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                }
201cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                Signature sig = new Signature(key);
20277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                readSignatures.set(idx, sig);
20377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                signatures[pos] = sig;
204cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                            }
205cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                        } catch (NumberFormatException e) {
206cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                            PackageManagerService.reportSettingsProblem(Log.WARN,
207cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                    "Error in package manager settings: <cert> "
20877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                            + "index " + index + " is not a number at "
20977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                            + parser.getPositionDescription());
2101137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root                        } catch (IllegalArgumentException e) {
2111137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root                            PackageManagerService.reportSettingsProblem(Log.WARN,
2121137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root                                    "Error in package manager settings: <cert> "
21377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                            + "index " + index + " has an invalid signature at "
21477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                            + parser.getPositionDescription() + ": "
21577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                            + e.getMessage());
21677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        }
21777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
21877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        if (flags != null) {
21977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            String flagsStr = parser.getAttributeValue(null, "flags");
22077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            if (flagsStr != null) {
22177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                try {
22277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    flags[pos] = Integer.parseInt(flagsStr);
22377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                } catch (NumberFormatException e) {
22477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    PackageManagerService.reportSettingsProblem(Log.WARN,
22577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                            "Error in package manager settings: <cert> "
22677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                                    + "flags " + flagsStr + " is not a number at "
22777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                                    + parser.getPositionDescription());
22877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                }
22977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            } else {
23077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                PackageManagerService.reportSettingsProblem(Log.WARN,
23177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                        "Error in package manager settings: <cert> has no"
23277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                                + " flags at " + parser.getPositionDescription());
23377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            }
234cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                        }
235cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    } else {
236cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                        PackageManagerService.reportSettingsProblem(Log.WARN,
237cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                                "Error in package manager settings: <cert> has"
23877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                        + " no index at " + parser.getPositionDescription());
239cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    }
240cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                } else {
241cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                    PackageManagerService.reportSettingsProblem(Log.WARN,
242cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                            "Error in package manager settings: too "
24377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    + "many <cert> tags, expected " + count
24477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    + " at " + parser.getPositionDescription());
24577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                }
2467ee17aa6b228a007129147c7a6e9ecba2a40d892Dan Cashman                pos++;
2477ee17aa6b228a007129147c7a6e9ecba2a40d892Dan Cashman                XmlUtils.skipCurrentTag(parser);
24877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            } else if (tagName.equals("pastSigs")) {
24977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                if (flags == null) {
25077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    // we haven't encountered pastSigs yet, go ahead
25177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    String countStr = parser.getAttributeValue(null, "count");
25277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    if (countStr == null) {
25377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        PackageManagerService.reportSettingsProblem(Log.WARN,
25477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                "Error in package manager settings: <pastSigs> has"
25577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                        + " no count at " + parser.getPositionDescription());
25677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        XmlUtils.skipCurrentTag(parser);
25777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    }
25877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    try {
25977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        final int pastSigsCount = Integer.parseInt(countStr);
26077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        Signature[] pastSignatures = new Signature[pastSigsCount];
26177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        int[] pastSignaturesFlags = new int[pastSigsCount];
26277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        int pastSigsPos = readCertsListXml(parser, readSignatures, pastSignatures,
26377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                pastSignaturesFlags, builder);
26477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        builder = builder
26577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                .setPastSigningCertificates(pastSignatures)
26677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                .setPastSigningCertificatesFlags(pastSignaturesFlags);
26777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman
26877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        if (pastSigsPos < pastSigsCount) {
26977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            // Should never happen -- there is an error in the written
27077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            // settings -- but if it does we don't want to generate
27177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            // a bad array.
27277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            Signature[] newSigs = new Signature[pastSigsPos];
27377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            System.arraycopy(pastSignatures, 0, newSigs, 0, pastSigsPos);
27477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            int[] newFlags = new int[pastSigsPos];
27577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            System.arraycopy(pastSignaturesFlags, 0, newFlags, 0, pastSigsPos);
27677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            builder = builder
27777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    .setPastSigningCertificates(newSigs)
27877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    .setPastSigningCertificatesFlags(newFlags);
27977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            PackageManagerService.reportSettingsProblem(Log.WARN,
28077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    "Error in package manager settings: <pastSigs> count does not "
28177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    + "match number of <cert> entries "
28277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    + parser.getPositionDescription());
28377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        }
28477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    } catch (NumberFormatException e) {
28577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        PackageManagerService.reportSettingsProblem(Log.WARN,
28677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                "Error in package manager settings: <pastSigs> "
28777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                        + "count " + countStr + " is not a number at "
28877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                        + parser.getPositionDescription());
28977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    }
29077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                } else {
29177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                    PackageManagerService.reportSettingsProblem(Log.WARN,
29277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                            "<pastSigs> encountered multiple times under the same <sigs> at "
29377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                    + parser.getPositionDescription());
29419e8803ddc1cfc74a9c976250da634140249d734Dan Cashman                    XmlUtils.skipCurrentTag(parser);
295cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                }
296cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            } else {
297cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                PackageManagerService.reportSettingsProblem(Log.WARN,
29877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        "Unknown element under <sigs>: "
29977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                                + parser.getName());
30033e17ae146ac6b13a6a1aea040730e86c927bb5aDan Cashman                XmlUtils.skipCurrentTag(parser);
301cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            }
302cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
30377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        return pos;
304cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
305cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
306cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    @Override
307cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    public String toString() {
308cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        StringBuffer buf = new StringBuffer(128);
309cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        buf.append("PackageSignatures{");
310cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        buf.append(Integer.toHexString(System.identityHashCode(this)));
311420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann        buf.append(" version:");
31277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        buf.append(mSigningDetails.signatureSchemeVersion);
313420d58a9d867a3ce96fb4ea98bd30ee4d44eab4dPatrick Baumann        buf.append(", signatures:[");
31477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        if (mSigningDetails.signatures != null) {
31577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            for (int i = 0; i < mSigningDetails.signatures.length; i++) {
316cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                if (i > 0) buf.append(", ");
317cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                buf.append(Integer.toHexString(
31877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        mSigningDetails.signatures[i].hashCode()));
319cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root            }
320cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        }
321be6c065d2c2ec960a266da88e6cd5bd33f15fde7Dan Cashman        buf.append("]");
32277029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        buf.append(", past signatures:[");
32377029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        if (mSigningDetails.pastSigningCertificates != null) {
32477029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            for (int i = 0; i < mSigningDetails.pastSigningCertificates.length; i++) {
32577029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                if (i > 0) buf.append(", ");
32677029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                buf.append(Integer.toHexString(
32777029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                        mSigningDetails.pastSigningCertificates[i].hashCode()));
32877029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                buf.append(" flags: ");
32977029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman                buf.append(Integer.toHexString(mSigningDetails.pastSigningCertificatesFlags[i]));
33077029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman            }
33177029c5b16351775cb2333369ef9a4bc1d9acf58Daniel Cashman        }
332be6c065d2c2ec960a266da88e6cd5bd33f15fde7Dan Cashman        buf.append("]}");
333cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        return buf.toString();
334cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
3357ee17aa6b228a007129147c7a6e9ecba2a40d892Dan Cashman}
336