Loading core/java/android/content/pm/PackageParser.java +9 −61 Original line number Diff line number Diff line Loading @@ -5785,52 +5785,32 @@ public class PackageParser { int AUTH = 16; } /** * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that * contains two pieces of information: * 1) the past signing certificates * 2) the flags that APK wants to assign to each of the past signing certificates. * * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates} * collection, represent the second piece of information and are viewed as capabilities. * They are an APK's way of telling the platform: "this is how I want to trust my old certs, * please enforce that." This is useful for situation where this app itself is using its * signing certificate as an authorization mechanism, like whether or not to allow another * app to have its SIGNATURE permission. An app could specify whether to allow other apps * signed by its old cert 'X' to still get a signature permission it defines, for example. */ @Nullable public final int[] pastSigningCertificatesFlags; /** A representation of unknown signing details. Use instead of null. */ public static final SigningDetails UNKNOWN = new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null); new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null); @VisibleForTesting public SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion, ArraySet<PublicKey> keys, Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags) { ArraySet<PublicKey> keys, Signature[] pastSigningCertificates) { this.signatures = signatures; this.signatureSchemeVersion = signatureSchemeVersion; this.publicKeys = keys; this.pastSigningCertificates = pastSigningCertificates; this.pastSigningCertificatesFlags = pastSigningCertificatesFlags; } public SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion, Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags) Signature[] pastSigningCertificates) throws CertificateException { this(signatures, signatureSchemeVersion, toSigningKeys(signatures), pastSigningCertificates, pastSigningCertificatesFlags); pastSigningCertificates); } public SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion) throws CertificateException { this(signatures, signatureSchemeVersion, null, null); this(signatures, signatureSchemeVersion, null); } public SigningDetails(SigningDetails orig) { Loading @@ -5844,17 +5824,14 @@ public class PackageParser { this.publicKeys = new ArraySet<>(orig.publicKeys); if (orig.pastSigningCertificates != null) { this.pastSigningCertificates = orig.pastSigningCertificates.clone(); this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone(); } else { this.pastSigningCertificates = null; this.pastSigningCertificatesFlags = null; } } else { this.signatures = null; this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN; this.publicKeys = null; this.pastSigningCertificates = null; this.pastSigningCertificatesFlags = null; } } Loading Loading @@ -5956,7 +5933,7 @@ public class PackageParser { if (Signature.areEffectiveMatch( oldDetails.signatures[0], pastSigningCertificates[i]) && pastSigningCertificatesFlags[i] == flags) { && pastSigningCertificates[i].getFlags() == flags) { return true; } } Loading Loading @@ -6006,7 +5983,7 @@ public class PackageParser { for (int i = 0; i < pastSigningCertificates.length - 1; i++) { if (pastSigningCertificates[i].equals(signature)) { if (flags == PAST_CERT_EXISTS || (flags & pastSigningCertificatesFlags[i]) == flags) { || (flags & pastSigningCertificates[i].getFlags()) == flags) { return true; } } Loading Loading @@ -6090,7 +6067,7 @@ public class PackageParser { pastSigningCertificates[i].toByteArray()); if (Arrays.equals(sha256Certificate, digest)) { if (flags == PAST_CERT_EXISTS || (flags & pastSigningCertificatesFlags[i]) == flags) { || (flags & pastSigningCertificates[i].getFlags()) == flags) { return true; } } Loading Loading @@ -6127,7 +6104,6 @@ public class PackageParser { dest.writeInt(this.signatureSchemeVersion); dest.writeArraySet(this.publicKeys); dest.writeTypedArray(this.pastSigningCertificates, flags); dest.writeIntArray(this.pastSigningCertificatesFlags); } protected SigningDetails(Parcel in) { Loading @@ -6136,7 +6112,6 @@ public class PackageParser { this.signatureSchemeVersion = in.readInt(); this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot); this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR); this.pastSigningCertificatesFlags = in.createIntArray(); } public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() { Loading Loading @@ -6175,9 +6150,6 @@ public class PackageParser { if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) { return false; } if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) { return false; } return true; } Loading @@ -6188,7 +6160,6 @@ public class PackageParser { result = 31 * result + signatureSchemeVersion; result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0); result = 31 * result + Arrays.hashCode(pastSigningCertificates); result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags); return result; } Loading @@ -6199,7 +6170,6 @@ public class PackageParser { private Signature[] mSignatures; private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN; private Signature[] mPastSigningCertificates; private int[] mPastSigningCertificatesFlags; @UnsupportedAppUsage public Builder() { Loading @@ -6226,34 +6196,12 @@ public class PackageParser { return this; } /** set the flags for the {@code pastSigningCertificates} */ @UnsupportedAppUsage public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) { mPastSigningCertificatesFlags = pastSigningCertificatesFlags; return this; } private void checkInvariants() { // must have signatures and scheme version set if (mSignatures == null) { throw new IllegalStateException("SigningDetails requires the current signing" + " certificates."); } // pastSigningCerts and flags must match up boolean pastMismatch = false; if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) { if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) { pastMismatch = true; } } else if (!(mPastSigningCertificates == null && mPastSigningCertificatesFlags == null)) { pastMismatch = true; } if (pastMismatch) { throw new IllegalStateException("SigningDetails must have a one to one mapping " + "between pastSigningCertificates and pastSigningCertificatesFlags"); } } /** build a {@code SigningDetails} object */ @UnsupportedAppUsage Loading @@ -6261,7 +6209,7 @@ public class PackageParser { throws CertificateException { checkInvariants(); return new SigningDetails(mSignatures, mSignatureSchemeVersion, mPastSigningCertificates, mPastSigningCertificatesFlags); mPastSigningCertificates); } } } Loading core/java/android/content/pm/Signature.java +31 −1 Original line number Diff line number Diff line Loading @@ -45,6 +45,20 @@ public class Signature implements Parcelable { private boolean mHaveHashCode; private SoftReference<String> mStringRef; private Certificate[] mCertificateChain; /** * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that * contains two pieces of information: * 1) the past signing certificates * 2) the flags that APK wants to assign to each of the past signing certificates. * * These flags represent the second piece of information and are viewed as capabilities. * They are an APK's way of telling the platform: "this is how I want to trust my old certs, * please enforce that." This is useful for situation where this app itself is using its * signing certificate as an authorization mechanism, like whether or not to allow another * app to have its SIGNATURE permission. An app could specify whether to allow other apps * signed by its old cert 'X' to still get a signature permission it defines, for example. */ private int mFlags; /** * Create Signature from an existing raw byte array. Loading Loading @@ -108,6 +122,22 @@ public class Signature implements Parcelable { mSignature = sig; } /** * Sets the flags representing the capabilities of the past signing certificate. * @hide */ public void setFlags(int flags) { this.mFlags = flags; } /** * Returns the flags representing the capabilities of the past signing certificate. * @hide */ public int getFlags() { return mFlags; } /** * Encode the Signature as ASCII text. */ Loading core/java/android/util/apk/ApkSignatureVerifier.java +4 −8 Original line number Diff line number Diff line Loading @@ -81,19 +81,17 @@ public class ApkSignatureVerifier { Certificate[][] signerCerts = new Certificate[][] { vSigner.certs }; Signature[] signerSigs = convertToSignatures(signerCerts); Signature[] pastSignerSigs = null; int[] pastSignerSigsFlags = null; if (vSigner.por != null) { // populate proof-of-rotation information pastSignerSigs = new Signature[vSigner.por.certs.size()]; pastSignerSigsFlags = new int[vSigner.por.flagsList.size()]; for (int i = 0; i < pastSignerSigs.length; i++) { pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded()); pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i); pastSignerSigs[i].setFlags(vSigner.por.flagsList.get(i)); } } return new PackageParser.SigningDetails( signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3, pastSignerSigs, pastSignerSigsFlags); pastSignerSigs); } catch (SignatureNotFoundException e) { // not signed with v3, try older if allowed if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) { Loading Loading @@ -323,19 +321,17 @@ public class ApkSignatureVerifier { Certificate[][] signerCerts = new Certificate[][] { vSigner.certs }; Signature[] signerSigs = convertToSignatures(signerCerts); Signature[] pastSignerSigs = null; int[] pastSignerSigsFlags = null; if (vSigner.por != null) { // populate proof-of-rotation information pastSignerSigs = new Signature[vSigner.por.certs.size()]; pastSignerSigsFlags = new int[vSigner.por.flagsList.size()]; for (int i = 0; i < pastSignerSigs.length; i++) { pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded()); pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i); pastSignerSigs[i].setFlags(vSigner.por.flagsList.get(i)); } } return new PackageParser.SigningDetails( signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3, pastSignerSigs, pastSignerSigsFlags); pastSignerSigs); } catch (SignatureNotFoundException e) { // not signed with v3, try older if allowed if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) { Loading services/core/java/com/android/server/pm/PackageSignatures.java +56 −51 Original line number Diff line number Diff line Loading @@ -16,18 +16,18 @@ package com.android.server.pm; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.annotation.NonNull; import android.content.pm.PackageParser; import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion; import android.content.pm.Signature; import android.util.Log; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.security.cert.CertificateException; import java.util.ArrayList; Loading Loading @@ -61,23 +61,22 @@ class PackageSignatures { serializer.attribute(null, "count", Integer.toString(mSigningDetails.signatures.length)); serializer.attribute(null, "schemeVersion", Integer.toString(mSigningDetails.signatureSchemeVersion)); writeCertsListXml(serializer, writtenSignatures, mSigningDetails.signatures, null); writeCertsListXml(serializer, writtenSignatures, mSigningDetails.signatures, false); // if we have past signer certificate information, write it out if (mSigningDetails.pastSigningCertificates != null) { serializer.startTag(null, "pastSigs"); serializer.attribute(null, "count", Integer.toString(mSigningDetails.pastSigningCertificates.length)); writeCertsListXml( serializer, writtenSignatures, mSigningDetails.pastSigningCertificates, mSigningDetails.pastSigningCertificatesFlags); writeCertsListXml(serializer, writtenSignatures, mSigningDetails.pastSigningCertificates, true); serializer.endTag(null, "pastSigs"); } serializer.endTag(null, tagName); } private void writeCertsListXml(XmlSerializer serializer, ArrayList<Signature> writtenSignatures, Signature[] signatures, int[] flags) throws IOException { Signature[] signatures, boolean isPastSigs) throws IOException { for (int i=0; i<signatures.length; i++) { serializer.startTag(null, "cert"); final Signature sig = signatures[i]; Loading @@ -96,8 +95,10 @@ class PackageSignatures { serializer.attribute(null, "index", Integer.toString(numWritten)); serializer.attribute(null, "key", sig.toCharsString()); } if (flags != null) { serializer.attribute(null, "flags", Integer.toString(flags[i])); // The flags attribute is only written for previous signatures to represent the // capabilities the developer wants to grant to the previous signing certificates. if (isPastSigs) { serializer.attribute(null, "flags", Integer.toString(sig.getFlags())); } serializer.endTag(null, "cert"); } Loading @@ -114,6 +115,7 @@ class PackageSignatures { "Error in package manager settings: <sigs> has" + " no count at " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); return; } final int count = Integer.parseInt(countStr); Loading @@ -128,16 +130,11 @@ class PackageSignatures { signatureSchemeVersion = Integer.parseInt(schemeVersionStr); } builder.setSignatureSchemeVersion(signatureSchemeVersion); Signature[] signatures = new Signature[count]; int pos = readCertsListXml(parser, readSignatures, signatures, null, builder); ArrayList<Signature> signatureList = new ArrayList<>(); int pos = readCertsListXml(parser, readSignatures, signatureList, count, false, builder); Signature[] signatures = signatureList.toArray(new Signature[signatureList.size()]); builder.setSignatures(signatures); if (pos < count) { // Should never happen -- there is an error in the written // settings -- but if it does we don't want to generate // a bad array. Signature[] newSigs = new Signature[pos]; System.arraycopy(signatures, 0, newSigs, 0, pos); builder = builder.setSignatures(newSigs); PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: <sigs> count does not match number of " + " <cert> entries" + parser.getPositionDescription()); Loading @@ -154,9 +151,9 @@ class PackageSignatures { } private int readCertsListXml(XmlPullParser parser, ArrayList<Signature> readSignatures, Signature[] signatures, int[] flags, PackageParser.SigningDetails.Builder builder) ArrayList<Signature> signatures, int count, boolean isPastSigs, PackageParser.SigningDetails.Builder builder) throws IOException, XmlPullParserException { int count = signatures.length; int pos = 0; int outerDepth = parser.getDepth(); Loading @@ -174,6 +171,7 @@ class PackageSignatures { if (pos < count) { String index = parser.getAttributeValue(null, "index"); if (index != null) { boolean signatureParsed = false; try { int idx = Integer.parseInt(index); String key = parser.getAttributeValue(null, "key"); Loading @@ -181,7 +179,8 @@ class PackageSignatures { if (idx >= 0 && idx < readSignatures.size()) { Signature sig = readSignatures.get(idx); if (sig != null) { signatures[pos] = readSignatures.get(idx); signatures.add(sig); signatureParsed = true; } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: <cert> " Loading @@ -195,12 +194,15 @@ class PackageSignatures { + parser.getPositionDescription()); } } else { while (readSignatures.size() <= idx) { // Create the signature first to prevent adding null entries to the // output List if the key value is invalid. Signature sig = new Signature(key); while (readSignatures.size() < idx) { readSignatures.add(null); } Signature sig = new Signature(key); readSignatures.set(idx, sig); signatures[pos] = sig; readSignatures.add(sig); signatures.add(sig); signatureParsed = true; } } catch (NumberFormatException e) { PackageManagerService.reportSettingsProblem(Log.WARN, Loading @@ -215,11 +217,22 @@ class PackageSignatures { + e.getMessage()); } if (flags != null) { if (isPastSigs) { String flagsStr = parser.getAttributeValue(null, "flags"); if (flagsStr != null) { try { flags[pos] = Integer.parseInt(flagsStr); int flagsValue = Integer.parseInt(flagsStr); // only modify the flags if the signature of the previous signer // was successfully parsed above if (signatureParsed) { signatures.get(signatures.size() - 1).setFlags(flagsValue); } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: signature not " + "available at index " + pos + " to set flags at " + parser.getPositionDescription()); } } catch (NumberFormatException e) { PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: <cert> " Loading @@ -246,7 +259,7 @@ class PackageSignatures { pos++; XmlUtils.skipCurrentTag(parser); } else if (tagName.equals("pastSigs")) { if (flags == null) { if (!isPastSigs) { // we haven't encountered pastSigs yet, go ahead String countStr = parser.getAttributeValue(null, "count"); if (countStr == null) { Loading @@ -254,28 +267,19 @@ class PackageSignatures { "Error in package manager settings: <pastSigs> has" + " no count at " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); continue; } try { final int pastSigsCount = Integer.parseInt(countStr); Signature[] pastSignatures = new Signature[pastSigsCount]; int[] pastSignaturesFlags = new int[pastSigsCount]; int pastSigsPos = readCertsListXml(parser, readSignatures, pastSignatures, pastSignaturesFlags, builder); builder = builder .setPastSigningCertificates(pastSignatures) .setPastSigningCertificatesFlags(pastSignaturesFlags); ArrayList<Signature> pastSignatureList = new ArrayList<>(); int pastSigsPos = readCertsListXml(parser, readSignatures, pastSignatureList, pastSigsCount, true, builder); Signature[] pastSignatures = pastSignatureList.toArray( new Signature[pastSignatureList.size()]); builder = builder.setPastSigningCertificates(pastSignatures); if (pastSigsPos < pastSigsCount) { // Should never happen -- there is an error in the written // settings -- but if it does we don't want to generate // a bad array. Signature[] newSigs = new Signature[pastSigsPos]; System.arraycopy(pastSignatures, 0, newSigs, 0, pastSigsPos); int[] newFlags = new int[pastSigsPos]; System.arraycopy(pastSignaturesFlags, 0, newFlags, 0, pastSigsPos); builder = builder .setPastSigningCertificates(newSigs) .setPastSigningCertificatesFlags(newFlags); PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: <pastSigs> count does not " + "match number of <cert> entries " Loading Loading @@ -326,7 +330,8 @@ class PackageSignatures { buf.append(Integer.toHexString( mSigningDetails.pastSigningCertificates[i].hashCode())); buf.append(" flags: "); buf.append(Integer.toHexString(mSigningDetails.pastSigningCertificatesFlags[i])); buf.append( Integer.toHexString(mSigningDetails.pastSigningCertificates[i].getFlags())); } } buf.append("]}"); Loading services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java +0 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/content/pm/PackageParser.java +9 −61 Original line number Diff line number Diff line Loading @@ -5785,52 +5785,32 @@ public class PackageParser { int AUTH = 16; } /** * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that * contains two pieces of information: * 1) the past signing certificates * 2) the flags that APK wants to assign to each of the past signing certificates. * * These flags, which have a one-to-one relationship for the {@code pastSigningCertificates} * collection, represent the second piece of information and are viewed as capabilities. * They are an APK's way of telling the platform: "this is how I want to trust my old certs, * please enforce that." This is useful for situation where this app itself is using its * signing certificate as an authorization mechanism, like whether or not to allow another * app to have its SIGNATURE permission. An app could specify whether to allow other apps * signed by its old cert 'X' to still get a signature permission it defines, for example. */ @Nullable public final int[] pastSigningCertificatesFlags; /** A representation of unknown signing details. Use instead of null. */ public static final SigningDetails UNKNOWN = new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null); new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null); @VisibleForTesting public SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion, ArraySet<PublicKey> keys, Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags) { ArraySet<PublicKey> keys, Signature[] pastSigningCertificates) { this.signatures = signatures; this.signatureSchemeVersion = signatureSchemeVersion; this.publicKeys = keys; this.pastSigningCertificates = pastSigningCertificates; this.pastSigningCertificatesFlags = pastSigningCertificatesFlags; } public SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion, Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags) Signature[] pastSigningCertificates) throws CertificateException { this(signatures, signatureSchemeVersion, toSigningKeys(signatures), pastSigningCertificates, pastSigningCertificatesFlags); pastSigningCertificates); } public SigningDetails(Signature[] signatures, @SignatureSchemeVersion int signatureSchemeVersion) throws CertificateException { this(signatures, signatureSchemeVersion, null, null); this(signatures, signatureSchemeVersion, null); } public SigningDetails(SigningDetails orig) { Loading @@ -5844,17 +5824,14 @@ public class PackageParser { this.publicKeys = new ArraySet<>(orig.publicKeys); if (orig.pastSigningCertificates != null) { this.pastSigningCertificates = orig.pastSigningCertificates.clone(); this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone(); } else { this.pastSigningCertificates = null; this.pastSigningCertificatesFlags = null; } } else { this.signatures = null; this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN; this.publicKeys = null; this.pastSigningCertificates = null; this.pastSigningCertificatesFlags = null; } } Loading Loading @@ -5956,7 +5933,7 @@ public class PackageParser { if (Signature.areEffectiveMatch( oldDetails.signatures[0], pastSigningCertificates[i]) && pastSigningCertificatesFlags[i] == flags) { && pastSigningCertificates[i].getFlags() == flags) { return true; } } Loading Loading @@ -6006,7 +5983,7 @@ public class PackageParser { for (int i = 0; i < pastSigningCertificates.length - 1; i++) { if (pastSigningCertificates[i].equals(signature)) { if (flags == PAST_CERT_EXISTS || (flags & pastSigningCertificatesFlags[i]) == flags) { || (flags & pastSigningCertificates[i].getFlags()) == flags) { return true; } } Loading Loading @@ -6090,7 +6067,7 @@ public class PackageParser { pastSigningCertificates[i].toByteArray()); if (Arrays.equals(sha256Certificate, digest)) { if (flags == PAST_CERT_EXISTS || (flags & pastSigningCertificatesFlags[i]) == flags) { || (flags & pastSigningCertificates[i].getFlags()) == flags) { return true; } } Loading Loading @@ -6127,7 +6104,6 @@ public class PackageParser { dest.writeInt(this.signatureSchemeVersion); dest.writeArraySet(this.publicKeys); dest.writeTypedArray(this.pastSigningCertificates, flags); dest.writeIntArray(this.pastSigningCertificatesFlags); } protected SigningDetails(Parcel in) { Loading @@ -6136,7 +6112,6 @@ public class PackageParser { this.signatureSchemeVersion = in.readInt(); this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot); this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR); this.pastSigningCertificatesFlags = in.createIntArray(); } public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() { Loading Loading @@ -6175,9 +6150,6 @@ public class PackageParser { if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) { return false; } if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) { return false; } return true; } Loading @@ -6188,7 +6160,6 @@ public class PackageParser { result = 31 * result + signatureSchemeVersion; result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0); result = 31 * result + Arrays.hashCode(pastSigningCertificates); result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags); return result; } Loading @@ -6199,7 +6170,6 @@ public class PackageParser { private Signature[] mSignatures; private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN; private Signature[] mPastSigningCertificates; private int[] mPastSigningCertificatesFlags; @UnsupportedAppUsage public Builder() { Loading @@ -6226,34 +6196,12 @@ public class PackageParser { return this; } /** set the flags for the {@code pastSigningCertificates} */ @UnsupportedAppUsage public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) { mPastSigningCertificatesFlags = pastSigningCertificatesFlags; return this; } private void checkInvariants() { // must have signatures and scheme version set if (mSignatures == null) { throw new IllegalStateException("SigningDetails requires the current signing" + " certificates."); } // pastSigningCerts and flags must match up boolean pastMismatch = false; if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) { if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) { pastMismatch = true; } } else if (!(mPastSigningCertificates == null && mPastSigningCertificatesFlags == null)) { pastMismatch = true; } if (pastMismatch) { throw new IllegalStateException("SigningDetails must have a one to one mapping " + "between pastSigningCertificates and pastSigningCertificatesFlags"); } } /** build a {@code SigningDetails} object */ @UnsupportedAppUsage Loading @@ -6261,7 +6209,7 @@ public class PackageParser { throws CertificateException { checkInvariants(); return new SigningDetails(mSignatures, mSignatureSchemeVersion, mPastSigningCertificates, mPastSigningCertificatesFlags); mPastSigningCertificates); } } } Loading
core/java/android/content/pm/Signature.java +31 −1 Original line number Diff line number Diff line Loading @@ -45,6 +45,20 @@ public class Signature implements Parcelable { private boolean mHaveHashCode; private SoftReference<String> mStringRef; private Certificate[] mCertificateChain; /** * APK Signature Scheme v3 includes support for adding a proof-of-rotation record that * contains two pieces of information: * 1) the past signing certificates * 2) the flags that APK wants to assign to each of the past signing certificates. * * These flags represent the second piece of information and are viewed as capabilities. * They are an APK's way of telling the platform: "this is how I want to trust my old certs, * please enforce that." This is useful for situation where this app itself is using its * signing certificate as an authorization mechanism, like whether or not to allow another * app to have its SIGNATURE permission. An app could specify whether to allow other apps * signed by its old cert 'X' to still get a signature permission it defines, for example. */ private int mFlags; /** * Create Signature from an existing raw byte array. Loading Loading @@ -108,6 +122,22 @@ public class Signature implements Parcelable { mSignature = sig; } /** * Sets the flags representing the capabilities of the past signing certificate. * @hide */ public void setFlags(int flags) { this.mFlags = flags; } /** * Returns the flags representing the capabilities of the past signing certificate. * @hide */ public int getFlags() { return mFlags; } /** * Encode the Signature as ASCII text. */ Loading
core/java/android/util/apk/ApkSignatureVerifier.java +4 −8 Original line number Diff line number Diff line Loading @@ -81,19 +81,17 @@ public class ApkSignatureVerifier { Certificate[][] signerCerts = new Certificate[][] { vSigner.certs }; Signature[] signerSigs = convertToSignatures(signerCerts); Signature[] pastSignerSigs = null; int[] pastSignerSigsFlags = null; if (vSigner.por != null) { // populate proof-of-rotation information pastSignerSigs = new Signature[vSigner.por.certs.size()]; pastSignerSigsFlags = new int[vSigner.por.flagsList.size()]; for (int i = 0; i < pastSignerSigs.length; i++) { pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded()); pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i); pastSignerSigs[i].setFlags(vSigner.por.flagsList.get(i)); } } return new PackageParser.SigningDetails( signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3, pastSignerSigs, pastSignerSigsFlags); pastSignerSigs); } catch (SignatureNotFoundException e) { // not signed with v3, try older if allowed if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) { Loading Loading @@ -323,19 +321,17 @@ public class ApkSignatureVerifier { Certificate[][] signerCerts = new Certificate[][] { vSigner.certs }; Signature[] signerSigs = convertToSignatures(signerCerts); Signature[] pastSignerSigs = null; int[] pastSignerSigsFlags = null; if (vSigner.por != null) { // populate proof-of-rotation information pastSignerSigs = new Signature[vSigner.por.certs.size()]; pastSignerSigsFlags = new int[vSigner.por.flagsList.size()]; for (int i = 0; i < pastSignerSigs.length; i++) { pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded()); pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i); pastSignerSigs[i].setFlags(vSigner.por.flagsList.get(i)); } } return new PackageParser.SigningDetails( signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3, pastSignerSigs, pastSignerSigsFlags); pastSignerSigs); } catch (SignatureNotFoundException e) { // not signed with v3, try older if allowed if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) { Loading
services/core/java/com/android/server/pm/PackageSignatures.java +56 −51 Original line number Diff line number Diff line Loading @@ -16,18 +16,18 @@ package com.android.server.pm; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import android.annotation.NonNull; import android.content.pm.PackageParser; import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion; import android.content.pm.Signature; import android.util.Log; import com.android.internal.util.XmlUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.security.cert.CertificateException; import java.util.ArrayList; Loading Loading @@ -61,23 +61,22 @@ class PackageSignatures { serializer.attribute(null, "count", Integer.toString(mSigningDetails.signatures.length)); serializer.attribute(null, "schemeVersion", Integer.toString(mSigningDetails.signatureSchemeVersion)); writeCertsListXml(serializer, writtenSignatures, mSigningDetails.signatures, null); writeCertsListXml(serializer, writtenSignatures, mSigningDetails.signatures, false); // if we have past signer certificate information, write it out if (mSigningDetails.pastSigningCertificates != null) { serializer.startTag(null, "pastSigs"); serializer.attribute(null, "count", Integer.toString(mSigningDetails.pastSigningCertificates.length)); writeCertsListXml( serializer, writtenSignatures, mSigningDetails.pastSigningCertificates, mSigningDetails.pastSigningCertificatesFlags); writeCertsListXml(serializer, writtenSignatures, mSigningDetails.pastSigningCertificates, true); serializer.endTag(null, "pastSigs"); } serializer.endTag(null, tagName); } private void writeCertsListXml(XmlSerializer serializer, ArrayList<Signature> writtenSignatures, Signature[] signatures, int[] flags) throws IOException { Signature[] signatures, boolean isPastSigs) throws IOException { for (int i=0; i<signatures.length; i++) { serializer.startTag(null, "cert"); final Signature sig = signatures[i]; Loading @@ -96,8 +95,10 @@ class PackageSignatures { serializer.attribute(null, "index", Integer.toString(numWritten)); serializer.attribute(null, "key", sig.toCharsString()); } if (flags != null) { serializer.attribute(null, "flags", Integer.toString(flags[i])); // The flags attribute is only written for previous signatures to represent the // capabilities the developer wants to grant to the previous signing certificates. if (isPastSigs) { serializer.attribute(null, "flags", Integer.toString(sig.getFlags())); } serializer.endTag(null, "cert"); } Loading @@ -114,6 +115,7 @@ class PackageSignatures { "Error in package manager settings: <sigs> has" + " no count at " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); return; } final int count = Integer.parseInt(countStr); Loading @@ -128,16 +130,11 @@ class PackageSignatures { signatureSchemeVersion = Integer.parseInt(schemeVersionStr); } builder.setSignatureSchemeVersion(signatureSchemeVersion); Signature[] signatures = new Signature[count]; int pos = readCertsListXml(parser, readSignatures, signatures, null, builder); ArrayList<Signature> signatureList = new ArrayList<>(); int pos = readCertsListXml(parser, readSignatures, signatureList, count, false, builder); Signature[] signatures = signatureList.toArray(new Signature[signatureList.size()]); builder.setSignatures(signatures); if (pos < count) { // Should never happen -- there is an error in the written // settings -- but if it does we don't want to generate // a bad array. Signature[] newSigs = new Signature[pos]; System.arraycopy(signatures, 0, newSigs, 0, pos); builder = builder.setSignatures(newSigs); PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: <sigs> count does not match number of " + " <cert> entries" + parser.getPositionDescription()); Loading @@ -154,9 +151,9 @@ class PackageSignatures { } private int readCertsListXml(XmlPullParser parser, ArrayList<Signature> readSignatures, Signature[] signatures, int[] flags, PackageParser.SigningDetails.Builder builder) ArrayList<Signature> signatures, int count, boolean isPastSigs, PackageParser.SigningDetails.Builder builder) throws IOException, XmlPullParserException { int count = signatures.length; int pos = 0; int outerDepth = parser.getDepth(); Loading @@ -174,6 +171,7 @@ class PackageSignatures { if (pos < count) { String index = parser.getAttributeValue(null, "index"); if (index != null) { boolean signatureParsed = false; try { int idx = Integer.parseInt(index); String key = parser.getAttributeValue(null, "key"); Loading @@ -181,7 +179,8 @@ class PackageSignatures { if (idx >= 0 && idx < readSignatures.size()) { Signature sig = readSignatures.get(idx); if (sig != null) { signatures[pos] = readSignatures.get(idx); signatures.add(sig); signatureParsed = true; } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: <cert> " Loading @@ -195,12 +194,15 @@ class PackageSignatures { + parser.getPositionDescription()); } } else { while (readSignatures.size() <= idx) { // Create the signature first to prevent adding null entries to the // output List if the key value is invalid. Signature sig = new Signature(key); while (readSignatures.size() < idx) { readSignatures.add(null); } Signature sig = new Signature(key); readSignatures.set(idx, sig); signatures[pos] = sig; readSignatures.add(sig); signatures.add(sig); signatureParsed = true; } } catch (NumberFormatException e) { PackageManagerService.reportSettingsProblem(Log.WARN, Loading @@ -215,11 +217,22 @@ class PackageSignatures { + e.getMessage()); } if (flags != null) { if (isPastSigs) { String flagsStr = parser.getAttributeValue(null, "flags"); if (flagsStr != null) { try { flags[pos] = Integer.parseInt(flagsStr); int flagsValue = Integer.parseInt(flagsStr); // only modify the flags if the signature of the previous signer // was successfully parsed above if (signatureParsed) { signatures.get(signatures.size() - 1).setFlags(flagsValue); } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: signature not " + "available at index " + pos + " to set flags at " + parser.getPositionDescription()); } } catch (NumberFormatException e) { PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: <cert> " Loading @@ -246,7 +259,7 @@ class PackageSignatures { pos++; XmlUtils.skipCurrentTag(parser); } else if (tagName.equals("pastSigs")) { if (flags == null) { if (!isPastSigs) { // we haven't encountered pastSigs yet, go ahead String countStr = parser.getAttributeValue(null, "count"); if (countStr == null) { Loading @@ -254,28 +267,19 @@ class PackageSignatures { "Error in package manager settings: <pastSigs> has" + " no count at " + parser.getPositionDescription()); XmlUtils.skipCurrentTag(parser); continue; } try { final int pastSigsCount = Integer.parseInt(countStr); Signature[] pastSignatures = new Signature[pastSigsCount]; int[] pastSignaturesFlags = new int[pastSigsCount]; int pastSigsPos = readCertsListXml(parser, readSignatures, pastSignatures, pastSignaturesFlags, builder); builder = builder .setPastSigningCertificates(pastSignatures) .setPastSigningCertificatesFlags(pastSignaturesFlags); ArrayList<Signature> pastSignatureList = new ArrayList<>(); int pastSigsPos = readCertsListXml(parser, readSignatures, pastSignatureList, pastSigsCount, true, builder); Signature[] pastSignatures = pastSignatureList.toArray( new Signature[pastSignatureList.size()]); builder = builder.setPastSigningCertificates(pastSignatures); if (pastSigsPos < pastSigsCount) { // Should never happen -- there is an error in the written // settings -- but if it does we don't want to generate // a bad array. Signature[] newSigs = new Signature[pastSigsPos]; System.arraycopy(pastSignatures, 0, newSigs, 0, pastSigsPos); int[] newFlags = new int[pastSigsPos]; System.arraycopy(pastSignaturesFlags, 0, newFlags, 0, pastSigsPos); builder = builder .setPastSigningCertificates(newSigs) .setPastSigningCertificatesFlags(newFlags); PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: <pastSigs> count does not " + "match number of <cert> entries " Loading Loading @@ -326,7 +330,8 @@ class PackageSignatures { buf.append(Integer.toHexString( mSigningDetails.pastSigningCertificates[i].hashCode())); buf.append(" flags: "); buf.append(Integer.toHexString(mSigningDetails.pastSigningCertificatesFlags[i])); buf.append( Integer.toHexString(mSigningDetails.pastSigningCertificates[i].getFlags())); } } buf.append("]}"); Loading
services/robotests/src/com/android/server/backup/fullbackup/AppMetadataBackupWriterTest.java +0 −1 File changed.Preview size limit exceeded, changes collapsed. Show changes