system app签名验证流程:
解释为什么预制到system/app下面开机却没有
PMS开机阶段会去scan /system/priv-app,/system/app,/vendor/app 等目录下的apk文件,扫描过程是会查看apk是否有效,无效就不安装到系统
以下是遇到的一个预制到system/priv-app目录下的应用,开机之后未正常显示的问题
alps\frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java
private PackageParser.Package addForInitLI(PackageParser.Package pkg,
@ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
@Nullable UserHandle user)
{
final boolean forceCollect = PackageManagerServiceUtils.isApkVerificationForced(
disabledPkgSetting);
// Full APK verification can be skipped during certificate collection, only if the file is
// in verified partition, or can be verified on access (when apk verity is enabled). In both
// cases, only data in Signing Block is verified instead of the whole file.
final boolean skipVerify = ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) || //PackageParser.PARSE_IS_SYSTEM_DIR
(forceCollect && canSkipFullPackageVerification(pkg)); //判断是否跳过平台验证签名
android.util.Log.i("cxy1","pkg.codePath="+pkg.codePath+"skipVerify ="+skipVerify+",forceCollect="+forceCollect);
collectCertificatesLI(pkgSetting, pkg, forceCollect, skipVerify);
}
PackageParser.PARSE_IS_SYSTEM_DIR属性的应用具体查看PackageManagerService的源码
1.1 第一类System app: 特定的shared uid的app 属于system app
例如:shared uid为android.uid.system,android.uid.phone,android.uid.log,android.uid.nfc,android.uid.bluetooth,android.uid.shell。这类app都被赋予了ApplicationInfo.FLAG_SYSTEM标志
1.2 第二类System app: 特定目录中的app属于system app
特定目录包括:/vendor/overlay,/system/framework,/system/priv-app,/system/app,/vendor/app,/oem/app。这些目录中的app,被视为system app。
private void collectCertificatesLI(PackageSetting ps, PackageParser.Package pkg,
boolean forceCollect, boolean skipVerify) throws PackageManagerException { //skipVerify 表示跳过平台验证签名
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
PackageParser.collectCertificates(pkg, skipVerify);//就算跳过平台验证签名也要check是否有签名
} catch (PackageParserException e) {
android.util.Log.i("cxy1","collectCertificates PackageParserException1");
throw PackageManagerException.from(e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
alps\frameworks\base\core\java\android\content\pm\PackageParser.java
private static void collectCertificates(Package pkg, File apkFile, boolean skipVerify,boolean skipPlatformCheck)
throws PackageParserException {
SigningDetails verified;
if (skipVerify) {
android.util.Log.i("cxy1","skipVerify yes mminSignatureScheme="+minSignatureScheme);
// systemDir APKs are already trusted, save time by not verifying
verified = ApkSignatureVerifier.plsCertsNoVerifyOnlyCerts( //跳过平台验证签名,但是要判断是否有证书
apkPath, minSignatureScheme);
} else {
android.util.Log.i("cxy1","verify apkPath="+apkPath);
// verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme);
verified = ApkSignatureVerifier.verify(apkPath, minSignatureScheme,skipPlatformCheck);//这里走平台验证签名流程
}
}
alps\frameworks\base\core\java\android\util\apk\ApkSignatureVerifier.java
public static PackageParser.SigningDetails plsCertsNoVerifyOnlyCerts(
String apkPath, int minSignatureSchemeVersion){
....
// v2 didn't work, try jarsigner
return verifyV1Signature(apkPath, false,false);//verifyFull false;skipPlatformCheck:是我自己加的一个参数,可以忽略
}
private static PackageParser.SigningDetails verifyV1Signature(
String apkPath, boolean verifyFull,boolean skipPlatformCheck)
throws PackageParserException {
....
jarFile = new StrictJarFile(
apkPath,
true, // collect certs
verifyFull); // whether to reject APK with stripped v2 signatures (b/27887819)
final List<ZipEntry> toVerify = new ArrayList<>();
// Gather certs from AndroidManifest.xml, which every APK must have, as an optimization
// to not need to verify the whole APK when verifyFUll == false.
final ZipEntry manifestEntry = jarFile.findEntry(
PackageParser.ANDROID_MANIFEST_FILENAME);
if (manifestEntry == null) {
throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
"Package " + apkPath + " has no manifest");
}
lastCerts = loadCertificates(jarFile, manifestEntry);//这里获取证书,如果不存在就抛出异常,预制的应用就无
安装提示:
//02-06 16:20:10.561700 936 936 W PackageManager: Failed to scan /system/priv-app/DeviceManager_service: Package /system/priv-app/DeviceManager_service/DeviceManager_service.apk has no certificates at entry AndroidManifest.xml
//调用 jarFile.getCertificateChains(entry);
if (ArrayUtils.isEmpty(lastCerts)) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES, "Package "
+ apkPath + " has no certificates at entry "
+ PackageParser.ANDROID_MANIFEST_FILENAME);
}
}
alps\frameworks\base\core\java\android\util\jar\StrictJarFile.java
public Certificate[][] getCertificateChains(ZipEntry ze) {
//isSigned = verifier.readCertificates() && verifier.isSignedJar();
if (isSigned) {//这里判断如果没有sign过就返回null,verifyV1Signature就会抛出异常
return verifier.getCertificateChains(ze.getName());
}
return null;
}
网友评论