Add v3 signature matching support during apex validation
Bug: 136002636 Test: atest CtsStagedInstallHostTestCases Change-Id: I7d0edb976c4228a26dd273d1c4b3d385d5acf906
This commit is contained in:
@@ -35,7 +35,6 @@ import android.content.pm.PackageParser.PackageParserException;
|
|||||||
import android.content.pm.PackageParser.SigningDetails;
|
import android.content.pm.PackageParser.SigningDetails;
|
||||||
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
|
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
|
||||||
import android.content.pm.ParceledListSlice;
|
import android.content.pm.ParceledListSlice;
|
||||||
import android.content.pm.Signature;
|
|
||||||
import android.content.rollback.IRollbackManager;
|
import android.content.rollback.IRollbackManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -106,8 +105,19 @@ public class StagingManager {
|
|||||||
return new ParceledListSlice<>(result);
|
return new ParceledListSlice<>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateApexSignature(String apexPath, String packageName)
|
/**
|
||||||
|
* Validates the signature used to sign the container of the new apex package
|
||||||
|
*
|
||||||
|
* @param newApexPkg The new apex package that is being installed
|
||||||
|
* @param installFlags flags related to the session
|
||||||
|
* @throws PackageManagerException
|
||||||
|
*/
|
||||||
|
private void validateApexSignature(PackageInfo newApexPkg, int installFlags)
|
||||||
throws PackageManagerException {
|
throws PackageManagerException {
|
||||||
|
// Get signing details of the new package
|
||||||
|
final String apexPath = newApexPkg.applicationInfo.sourceDir;
|
||||||
|
final String packageName = newApexPkg.packageName;
|
||||||
|
|
||||||
final SigningDetails signingDetails;
|
final SigningDetails signingDetails;
|
||||||
try {
|
try {
|
||||||
signingDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR);
|
signingDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR);
|
||||||
@@ -116,9 +126,10 @@ public class StagingManager {
|
|||||||
"Failed to parse APEX package " + apexPath, e);
|
"Failed to parse APEX package " + apexPath, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
final PackageInfo packageInfo = mApexManager.getPackageInfo(packageName,
|
// Get signing details of the existing package
|
||||||
|
final PackageInfo existingApexPkg = mApexManager.getPackageInfo(packageName,
|
||||||
ApexManager.MATCH_ACTIVE_PACKAGE);
|
ApexManager.MATCH_ACTIVE_PACKAGE);
|
||||||
if (packageInfo == null) {
|
if (existingApexPkg == null) {
|
||||||
// This should never happen, because submitSessionToApexService ensures that no new
|
// This should never happen, because submitSessionToApexService ensures that no new
|
||||||
// apexes were installed.
|
// apexes were installed.
|
||||||
throw new IllegalStateException("Unknown apex package " + packageName);
|
throw new IllegalStateException("Unknown apex package " + packageName);
|
||||||
@@ -127,22 +138,22 @@ public class StagingManager {
|
|||||||
final SigningDetails existingSigningDetails;
|
final SigningDetails existingSigningDetails;
|
||||||
try {
|
try {
|
||||||
existingSigningDetails = ApkSignatureVerifier.verify(
|
existingSigningDetails = ApkSignatureVerifier.verify(
|
||||||
packageInfo.applicationInfo.sourceDir, SignatureSchemeVersion.JAR);
|
existingApexPkg.applicationInfo.sourceDir, SignatureSchemeVersion.JAR);
|
||||||
} catch (PackageParserException e) {
|
} catch (PackageParserException e) {
|
||||||
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
|
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
|
||||||
"Failed to parse APEX package " + packageInfo.applicationInfo.sourceDir, e);
|
"Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we have both sets of signatures, demand that they're an exact match.
|
// Verify signing details for upgrade
|
||||||
if (Signature.areExactMatch(existingSigningDetails.signatures, signingDetails.signatures)) {
|
if (signingDetails.checkCapability(existingSigningDetails,
|
||||||
|
PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
|
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
|
||||||
"APK-container signature verification failed for package "
|
"APK-container signature of APEX package " + packageName + " with version "
|
||||||
+ packageName + ". Signature of file "
|
+ newApexPkg.versionCodeMajor + " and path " + apexPath + " is not"
|
||||||
+ apexPath + " does not match the signature of "
|
+ " compatible with the one currently installed on device");
|
||||||
+ " the package already installed.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PackageInfo> submitSessionToApexService(
|
private List<PackageInfo> submitSessionToApexService(
|
||||||
@@ -239,8 +250,7 @@ public class StagingManager {
|
|||||||
try {
|
try {
|
||||||
final List<PackageInfo> apexPackages = submitSessionToApexService(session);
|
final List<PackageInfo> apexPackages = submitSessionToApexService(session);
|
||||||
for (PackageInfo apexPackage : apexPackages) {
|
for (PackageInfo apexPackage : apexPackages) {
|
||||||
validateApexSignature(apexPackage.applicationInfo.sourceDir,
|
validateApexSignature(apexPackage, session.params.installFlags);
|
||||||
apexPackage.packageName);
|
|
||||||
}
|
}
|
||||||
} catch (PackageManagerException e) {
|
} catch (PackageManagerException e) {
|
||||||
session.setStagedSessionFailed(e.error, e.getMessage());
|
session.setStagedSessionFailed(e.error, e.getMessage());
|
||||||
|
|||||||
Reference in New Issue
Block a user