Loading services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java +55 −36 Original line number Original line Diff line number Diff line Loading @@ -39,13 +39,20 @@ import android.content.integrity.Rule; import android.content.pm.PackageInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; import android.content.pm.PackageUserState; import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice; import android.content.pm.Signature; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.content.pm.parsing.ApkParseUtils; import android.content.pm.parsing.PackageInfoUtils; import android.content.pm.parsing.ParsedPackage; import android.net.Uri; import android.net.Uri; import android.os.Binder; import android.os.Binder; import android.os.Bundle; import android.os.Bundle; import android.os.Handler; import android.os.Handler; import android.os.HandlerThread; import android.os.HandlerThread; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings; import android.util.Slog; import android.util.Slog; Loading @@ -67,6 +74,7 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Collections; import java.util.Collections; import java.util.HashMap; import java.util.HashMap; Loading Loading @@ -260,16 +268,25 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { return; return; } } String appCert = getCertificateFingerprint(packageInfo); List<String> appCertificates = getCertificateFingerprint(packageInfo); List<String> installerCertificates = getInstallerCertificateFingerprint(installerPackageName); // TODO (b/148373316): Figure out what field contains which fields are populated for // rotated and the multiple signers. Until then, return the first certificate. String appCert = appCertificates.isEmpty() ? "" : appCertificates.get(0); String installerCert = installerCertificates.isEmpty() ? "" : installerCertificates.get(0); Slog.w(TAG, appCertificates.toString()); AppInstallMetadata.Builder builder = new AppInstallMetadata.Builder(); AppInstallMetadata.Builder builder = new AppInstallMetadata.Builder(); builder.setPackageName(getPackageNameNormalized(packageName)); builder.setPackageName(getPackageNameNormalized(packageName)); builder.setAppCertificate(appCert == null ? "" : appCert); builder.setAppCertificate(appCert); builder.setVersionCode(intent.getLongExtra(EXTRA_LONG_VERSION_CODE, -1)); builder.setVersionCode(intent.getLongExtra(EXTRA_LONG_VERSION_CODE, -1)); builder.setInstallerName(getPackageNameNormalized(installerPackageName)); builder.setInstallerName(getPackageNameNormalized(installerPackageName)); builder.setInstallerCertificate( builder.setInstallerCertificate(installerCert); getInstallerCertificateFingerprint(installerPackageName)); builder.setIsPreInstalled(isSystemApp(packageName)); builder.setIsPreInstalled(isSystemApp(packageName)); AppInstallMetadata appInstallMetadata = builder.build(); AppInstallMetadata appInstallMetadata = builder.build(); Loading Loading @@ -399,25 +416,29 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { } } } } private String getCertificateFingerprint(@NonNull PackageInfo packageInfo) { private List<String> getInstallerCertificateFingerprint(String installer) { return getFingerprint(getSignature(packageInfo)); } private String getInstallerCertificateFingerprint(String installer) { if (installer.equals(ADB_INSTALLER) || installer.equals(UNKNOWN_INSTALLER)) { if (installer.equals(ADB_INSTALLER) || installer.equals(UNKNOWN_INSTALLER)) { return INSTALLER_CERT_NOT_APPLICABLE; return Collections.emptyList(); } } try { try { PackageInfo installerInfo = PackageInfo installerInfo = mContext.getPackageManager() mContext.getPackageManager() .getPackageInfo(installer, PackageManager.GET_SIGNATURES); .getPackageInfo(installer, PackageManager.GET_SIGNING_CERTIFICATES); return getCertificateFingerprint(installerInfo); return getCertificateFingerprint(installerInfo); } catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) { Slog.i(TAG, "Installer package " + installer + " not found."); Slog.i(TAG, "Installer package " + installer + " not found."); return ""; return Collections.emptyList(); } } } } private List<String> getCertificateFingerprint(@NonNull PackageInfo packageInfo) { ArrayList<String> certificateFingerprints = new ArrayList(); for (Signature signature : getSignatures(packageInfo)) { certificateFingerprints.add(getFingerprint(signature)); } return certificateFingerprints; } /** Get the allowed installers and their associated certificate hashes from <meta-data> tag. */ /** Get the allowed installers and their associated certificate hashes from <meta-data> tag. */ private Map<String, String> getAllowedInstallers(@NonNull PackageInfo packageInfo) { private Map<String, String> getAllowedInstallers(@NonNull PackageInfo packageInfo) { Map<String, String> packageCertMap = new HashMap<>(); Map<String, String> packageCertMap = new HashMap<>(); Loading Loading @@ -445,12 +466,15 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { return packageCertMap; return packageCertMap; } } private static Signature getSignature(@NonNull PackageInfo packageInfo) { private static Signature[] getSignatures(@NonNull PackageInfo packageInfo) { if (packageInfo.signatures == null || packageInfo.signatures.length < 1) { SigningInfo signingInfo = packageInfo.signingInfo; if (signingInfo == null || signingInfo.getApkContentsSigners().length < 1) { throw new IllegalArgumentException("Package signature not found in " + packageInfo); throw new IllegalArgumentException("Package signature not found in " + packageInfo); } } // Only the first element is guaranteed to be present. return packageInfo.signatures[0]; // We are only interested in evaluating the active signatures. return signingInfo.getApkContentsSigners(); } } private static String getFingerprint(Signature cert) { private static String getFingerprint(Signature cert) { Loading Loading @@ -489,20 +513,14 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { if (installationPath == null) { if (installationPath == null) { throw new IllegalArgumentException("Installation path is null, package not found"); throw new IllegalArgumentException("Installation path is null, package not found"); } } PackageInfo packageInfo; PackageParser parser = new PackageParser(); try { try { // The installation path will be a directory for a multi-apk install on L+ ParsedPackage pkg = parser.parseParsedPackage(installationPath, 0, false); if (installationPath.isDirectory()) { int flags = PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_META_DATA; packageInfo = getMultiApkInfo(installationPath); ApkParseUtils.collectCertificates(pkg, false); } else { return PackageInfoUtils.generate(pkg, null, flags, 0, 0, null, new PackageUserState(), packageInfo = UserHandle.getCallingUserId()); mContext.getPackageManager() .getPackageArchiveInfo( installationPath.getPath(), PackageManager.GET_SIGNATURES | PackageManager.GET_META_DATA); } return packageInfo; } catch (Exception e) { } catch (Exception e) { throw new IllegalArgumentException("Exception reading " + dataUri, e); throw new IllegalArgumentException("Exception reading " + dataUri, e); } } Loading @@ -515,7 +533,8 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { mContext.getPackageManager() mContext.getPackageManager() .getPackageArchiveInfo( .getPackageArchiveInfo( baseFile.getAbsolutePath(), baseFile.getAbsolutePath(), PackageManager.GET_SIGNATURES | PackageManager.GET_META_DATA); PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_META_DATA); if (basePackageInfo == null) { if (basePackageInfo == null) { for (File apkFile : multiApkDirectory.listFiles()) { for (File apkFile : multiApkDirectory.listFiles()) { Loading services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -423,7 +423,8 @@ public class AppIntegrityManagerServiceImplTest { PackageInfo packageInfo = PackageInfo packageInfo = mRealContext mRealContext .getPackageManager() .getPackageManager() .getPackageInfo(TEST_FRAMEWORK_PACKAGE, PackageManager.GET_SIGNATURES); .getPackageInfo(TEST_FRAMEWORK_PACKAGE, PackageManager.GET_SIGNING_CERTIFICATES); doReturn(packageInfo).when(mSpyPackageManager).getPackageInfo(eq(INSTALLER), anyInt()); doReturn(packageInfo).when(mSpyPackageManager).getPackageInfo(eq(INSTALLER), anyInt()); doReturn(1).when(mSpyPackageManager).getPackageUid(eq(INSTALLER), anyInt()); doReturn(1).when(mSpyPackageManager).getPackageUid(eq(INSTALLER), anyInt()); return makeVerificationIntent(INSTALLER); return makeVerificationIntent(INSTALLER); Loading Loading
services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java +55 −36 Original line number Original line Diff line number Diff line Loading @@ -39,13 +39,20 @@ import android.content.integrity.Rule; import android.content.pm.PackageInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageParser; import android.content.pm.PackageUserState; import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice; import android.content.pm.Signature; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.content.pm.parsing.ApkParseUtils; import android.content.pm.parsing.PackageInfoUtils; import android.content.pm.parsing.ParsedPackage; import android.net.Uri; import android.net.Uri; import android.os.Binder; import android.os.Binder; import android.os.Bundle; import android.os.Bundle; import android.os.Handler; import android.os.Handler; import android.os.HandlerThread; import android.os.HandlerThread; import android.os.UserHandle; import android.provider.Settings; import android.provider.Settings; import android.util.Slog; import android.util.Slog; Loading @@ -67,6 +74,7 @@ import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.Collections; import java.util.Collections; import java.util.HashMap; import java.util.HashMap; Loading Loading @@ -260,16 +268,25 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { return; return; } } String appCert = getCertificateFingerprint(packageInfo); List<String> appCertificates = getCertificateFingerprint(packageInfo); List<String> installerCertificates = getInstallerCertificateFingerprint(installerPackageName); // TODO (b/148373316): Figure out what field contains which fields are populated for // rotated and the multiple signers. Until then, return the first certificate. String appCert = appCertificates.isEmpty() ? "" : appCertificates.get(0); String installerCert = installerCertificates.isEmpty() ? "" : installerCertificates.get(0); Slog.w(TAG, appCertificates.toString()); AppInstallMetadata.Builder builder = new AppInstallMetadata.Builder(); AppInstallMetadata.Builder builder = new AppInstallMetadata.Builder(); builder.setPackageName(getPackageNameNormalized(packageName)); builder.setPackageName(getPackageNameNormalized(packageName)); builder.setAppCertificate(appCert == null ? "" : appCert); builder.setAppCertificate(appCert); builder.setVersionCode(intent.getLongExtra(EXTRA_LONG_VERSION_CODE, -1)); builder.setVersionCode(intent.getLongExtra(EXTRA_LONG_VERSION_CODE, -1)); builder.setInstallerName(getPackageNameNormalized(installerPackageName)); builder.setInstallerName(getPackageNameNormalized(installerPackageName)); builder.setInstallerCertificate( builder.setInstallerCertificate(installerCert); getInstallerCertificateFingerprint(installerPackageName)); builder.setIsPreInstalled(isSystemApp(packageName)); builder.setIsPreInstalled(isSystemApp(packageName)); AppInstallMetadata appInstallMetadata = builder.build(); AppInstallMetadata appInstallMetadata = builder.build(); Loading Loading @@ -399,25 +416,29 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { } } } } private String getCertificateFingerprint(@NonNull PackageInfo packageInfo) { private List<String> getInstallerCertificateFingerprint(String installer) { return getFingerprint(getSignature(packageInfo)); } private String getInstallerCertificateFingerprint(String installer) { if (installer.equals(ADB_INSTALLER) || installer.equals(UNKNOWN_INSTALLER)) { if (installer.equals(ADB_INSTALLER) || installer.equals(UNKNOWN_INSTALLER)) { return INSTALLER_CERT_NOT_APPLICABLE; return Collections.emptyList(); } } try { try { PackageInfo installerInfo = PackageInfo installerInfo = mContext.getPackageManager() mContext.getPackageManager() .getPackageInfo(installer, PackageManager.GET_SIGNATURES); .getPackageInfo(installer, PackageManager.GET_SIGNING_CERTIFICATES); return getCertificateFingerprint(installerInfo); return getCertificateFingerprint(installerInfo); } catch (PackageManager.NameNotFoundException e) { } catch (PackageManager.NameNotFoundException e) { Slog.i(TAG, "Installer package " + installer + " not found."); Slog.i(TAG, "Installer package " + installer + " not found."); return ""; return Collections.emptyList(); } } } } private List<String> getCertificateFingerprint(@NonNull PackageInfo packageInfo) { ArrayList<String> certificateFingerprints = new ArrayList(); for (Signature signature : getSignatures(packageInfo)) { certificateFingerprints.add(getFingerprint(signature)); } return certificateFingerprints; } /** Get the allowed installers and their associated certificate hashes from <meta-data> tag. */ /** Get the allowed installers and their associated certificate hashes from <meta-data> tag. */ private Map<String, String> getAllowedInstallers(@NonNull PackageInfo packageInfo) { private Map<String, String> getAllowedInstallers(@NonNull PackageInfo packageInfo) { Map<String, String> packageCertMap = new HashMap<>(); Map<String, String> packageCertMap = new HashMap<>(); Loading Loading @@ -445,12 +466,15 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { return packageCertMap; return packageCertMap; } } private static Signature getSignature(@NonNull PackageInfo packageInfo) { private static Signature[] getSignatures(@NonNull PackageInfo packageInfo) { if (packageInfo.signatures == null || packageInfo.signatures.length < 1) { SigningInfo signingInfo = packageInfo.signingInfo; if (signingInfo == null || signingInfo.getApkContentsSigners().length < 1) { throw new IllegalArgumentException("Package signature not found in " + packageInfo); throw new IllegalArgumentException("Package signature not found in " + packageInfo); } } // Only the first element is guaranteed to be present. return packageInfo.signatures[0]; // We are only interested in evaluating the active signatures. return signingInfo.getApkContentsSigners(); } } private static String getFingerprint(Signature cert) { private static String getFingerprint(Signature cert) { Loading Loading @@ -489,20 +513,14 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { if (installationPath == null) { if (installationPath == null) { throw new IllegalArgumentException("Installation path is null, package not found"); throw new IllegalArgumentException("Installation path is null, package not found"); } } PackageInfo packageInfo; PackageParser parser = new PackageParser(); try { try { // The installation path will be a directory for a multi-apk install on L+ ParsedPackage pkg = parser.parseParsedPackage(installationPath, 0, false); if (installationPath.isDirectory()) { int flags = PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_META_DATA; packageInfo = getMultiApkInfo(installationPath); ApkParseUtils.collectCertificates(pkg, false); } else { return PackageInfoUtils.generate(pkg, null, flags, 0, 0, null, new PackageUserState(), packageInfo = UserHandle.getCallingUserId()); mContext.getPackageManager() .getPackageArchiveInfo( installationPath.getPath(), PackageManager.GET_SIGNATURES | PackageManager.GET_META_DATA); } return packageInfo; } catch (Exception e) { } catch (Exception e) { throw new IllegalArgumentException("Exception reading " + dataUri, e); throw new IllegalArgumentException("Exception reading " + dataUri, e); } } Loading @@ -515,7 +533,8 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub { mContext.getPackageManager() mContext.getPackageManager() .getPackageArchiveInfo( .getPackageArchiveInfo( baseFile.getAbsolutePath(), baseFile.getAbsolutePath(), PackageManager.GET_SIGNATURES | PackageManager.GET_META_DATA); PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_META_DATA); if (basePackageInfo == null) { if (basePackageInfo == null) { for (File apkFile : multiApkDirectory.listFiles()) { for (File apkFile : multiApkDirectory.listFiles()) { Loading
services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java +2 −1 Original line number Original line Diff line number Diff line Loading @@ -423,7 +423,8 @@ public class AppIntegrityManagerServiceImplTest { PackageInfo packageInfo = PackageInfo packageInfo = mRealContext mRealContext .getPackageManager() .getPackageManager() .getPackageInfo(TEST_FRAMEWORK_PACKAGE, PackageManager.GET_SIGNATURES); .getPackageInfo(TEST_FRAMEWORK_PACKAGE, PackageManager.GET_SIGNING_CERTIFICATES); doReturn(packageInfo).when(mSpyPackageManager).getPackageInfo(eq(INSTALLER), anyInt()); doReturn(packageInfo).when(mSpyPackageManager).getPackageInfo(eq(INSTALLER), anyInt()); doReturn(1).when(mSpyPackageManager).getPackageUid(eq(INSTALLER), anyInt()); doReturn(1).when(mSpyPackageManager).getPackageUid(eq(INSTALLER), anyInt()); return makeVerificationIntent(INSTALLER); return makeVerificationIntent(INSTALLER); Loading