Skip to content

Commit

Permalink
Self-Check: Also verify that PackageInfo.signingInfo was spoofed.
Browse files Browse the repository at this point in the history
  • Loading branch information
mar-v-in committed Dec 12, 2024
1 parent cc03a58 commit b9b7278
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,16 @@ public static void checkPackageUid(Context context, String packageName, int call
@Deprecated
@Nullable
public static String firstSignatureDigest(Context context, String packageName) {
return firstSignatureDigest(context.getPackageManager(), packageName);
return firstSignatureDigest(context, packageName, false);
}

/**
* @deprecated We should stop using SHA-1 for certificate fingerprints!
*/
@Deprecated
@Nullable
public static String firstSignatureDigest(Context context, String packageName, boolean useSigningInfo) {
return firstSignatureDigest(context.getPackageManager(), packageName, useSigningInfo);
}

/**
Expand All @@ -103,13 +112,33 @@ public static String firstSignatureDigest(Context context, String packageName) {
@Deprecated
@Nullable
public static String firstSignatureDigest(PackageManager packageManager, String packageName) {
return firstSignatureDigest(packageManager, packageName, false);
}

/**
* @deprecated We should stop using SHA-1 for certificate fingerprints!
*/
@Deprecated
@Nullable
public static String firstSignatureDigest(PackageManager packageManager, String packageName, boolean useSigningInfo) {
final PackageInfo info;
try {
info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES | (useSigningInfo && SDK_INT >= 28 ? PackageManager.GET_SIGNING_CERTIFICATES : 0));
} catch (PackageManager.NameNotFoundException e) {
return null;
}
if (info != null && info.signatures != null && info.signatures.length > 0) {
if (info == null) return null;
if (SDK_INT >= 28 && useSigningInfo && info.signingInfo != null) {
if (!info.signingInfo.hasMultipleSigners()) {
for (Signature sig : info.signingInfo.getSigningCertificateHistory()) {
String digest = sha1sum(sig.toByteArray());
if (digest != null) {
return digest;
}
}
}
}
if (info.signatures != null) {
for (Signature sig : info.signatures) {
String digest = sha1sum(sig.toByteArray());
if (digest != null) {
Expand All @@ -135,13 +164,33 @@ public static byte[] firstSignatureDigestBytes(Context context, String packageNa
@Deprecated
@Nullable
public static byte[] firstSignatureDigestBytes(PackageManager packageManager, String packageName) {
return firstSignatureDigestBytes(packageManager, packageName, false);
}

/**
* @deprecated We should stop using SHA-1 for certificate fingerprints!
*/
@Deprecated
@Nullable
public static byte[] firstSignatureDigestBytes(PackageManager packageManager, String packageName, boolean useSigningInfo) {
final PackageInfo info;
try {
info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES | (useSigningInfo && SDK_INT >= 28 ? PackageManager.GET_SIGNING_CERTIFICATES : 0));
} catch (PackageManager.NameNotFoundException e) {
return null;
}
if (info != null && info.signatures != null && info.signatures.length > 0) {
if (info == null) return null;
if (SDK_INT >= 28 && useSigningInfo && info.signingInfo != null) {
if (!info.signingInfo.hasMultipleSigners()) {
for (Signature sig : info.signingInfo.getSigningCertificateHistory()) {
byte[] digest = sha1bytes(sig.toByteArray());
if (digest != null) {
return digest;
}
}
}
}
if (info.signatures != null) {
for (Signature sig : info.signatures) {
byte[] digest = sha1bytes(sig.toByteArray());
if (digest != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ private void addPackageInstalledAndSignedResult(Context context, ResultCollector
}

private boolean addPackageSignedResult(Context context, ResultCollector collector, String nicePackageName, String androidPackageName, String signatureHash) {
boolean hashMatches = signatureHash.equals(PackageUtils.firstSignatureDigest(context, androidPackageName));
boolean hashMatches = signatureHash.equals(PackageUtils.firstSignatureDigest(context, androidPackageName, true)) &&
signatureHash.equals(PackageUtils.firstSignatureDigest(context, androidPackageName, false));
collector.addResult(context.getString(R.string.self_check_name_correct_sig, nicePackageName),
hashMatches ? Positive : Negative,
context.getString(R.string.self_check_resolution_correct_sig, nicePackageName),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ private boolean addSystemSpoofsSignature(Context context, ResultCollector collec
if (knowsPermission) {
grantsPermission = ContextCompat.checkSelfPermission(context, FAKE_SIGNATURE_PERMISSION) == PERMISSION_GRANTED;
}
boolean spoofsSignature = GMS_PACKAGE_SIGNATURE_SHA1.equals(PackageUtils.firstSignatureDigest(context, Constants.GMS_PACKAGE_NAME));
boolean spoofsSignature = GMS_PACKAGE_SIGNATURE_SHA1.equals(PackageUtils.firstSignatureDigest(context, Constants.GMS_PACKAGE_NAME, true)) &&
GMS_PACKAGE_SIGNATURE_SHA1.equals(PackageUtils.firstSignatureDigest(context, Constants.GMS_PACKAGE_NAME, false));
if (knowsPermission && !spoofsSignature && !grantsPermission) {
collector.addResult(
context.getString(R.string.self_check_name_system_spoofs),
Expand Down

0 comments on commit b9b7278

Please sign in to comment.