aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/android/apksig/ApkVerifier.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/android/apksig/ApkVerifier.java')
-rw-r--r--src/main/java/com/android/apksig/ApkVerifier.java60
1 files changed, 52 insertions, 8 deletions
diff --git a/src/main/java/com/android/apksig/ApkVerifier.java b/src/main/java/com/android/apksig/ApkVerifier.java
index 078996a..50b3d9f 100644
--- a/src/main/java/com/android/apksig/ApkVerifier.java
+++ b/src/main/java/com/android/apksig/ApkVerifier.java
@@ -27,6 +27,7 @@ import static com.android.apksig.internal.apk.ApkSigningBlockUtils.VERSION_APK_S
import static com.android.apksig.internal.apk.ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V4;
import static com.android.apksig.internal.apk.ApkSigningBlockUtils.VERSION_JAR_SIGNATURE_SCHEME;
import static com.android.apksig.internal.apk.ApkSigningBlockUtils.VERSION_SOURCE_STAMP;
+import static com.android.apksig.internal.apk.ApkSigningBlockUtils.toHex;
import static com.android.apksig.internal.apk.v1.V1SchemeConstants.MANIFEST_ENTRY_NAME;
import static com.android.apksig.internal.apk.v3.V3SchemeConstants.MIN_SDK_WITH_V31_SUPPORT;
@@ -510,21 +511,36 @@ public class ApkVerifier {
List<ApkSigningBlockUtils.Result.SignerInfo.ContentDigest> digestsFromV4 =
v4Signers.get(0).getContentDigests();
if (digestsFromV4.size() != 1) {
- result.addError(Issue.V4_SIG_V2_V3_DIGESTS_MISMATCH);
+ result.addError(Issue.V4_SIG_UNEXPECTED_DIGESTS, digestsFromV4.size());
+ if (digestsFromV4.isEmpty()) {
+ return result;
+ }
}
final byte[] digestFromV4 = digestsFromV4.get(0).getValue();
if (result.isVerifiedUsingV3Scheme()) {
- int expectedSize = result.isVerifiedUsingV31Scheme() ? 2 : 1;
+ final boolean isV31 = result.isVerifiedUsingV31Scheme();
+ final int expectedSize = isV31 ? 2 : 1;
if (v4Signers.size() != expectedSize) {
- result.addError(Issue.V4_SIG_MULTIPLE_SIGNERS);
+ result.addError(isV31 ? Issue.V41_SIG_NEEDS_TWO_SIGNERS
+ : Issue.V4_SIG_MULTIPLE_SIGNERS);
+ return result;
}
checkV4Signer(result.getV3SchemeSigners(), v4Signers.get(0).mCerts, digestFromV4,
result);
- if (result.isVerifiedUsingV31Scheme()) {
+ if (isV31) {
+ List<ApkSigningBlockUtils.Result.SignerInfo.ContentDigest> digestsFromV41 =
+ v4Signers.get(1).getContentDigests();
+ if (digestsFromV41.size() != 1) {
+ result.addError(Issue.V4_SIG_UNEXPECTED_DIGESTS, digestsFromV41.size());
+ if (digestsFromV41.isEmpty()) {
+ return result;
+ }
+ }
+ final byte[] digestFromV41 = digestsFromV41.get(0).getValue();
checkV4Signer(result.getV31SchemeSigners(), v4Signers.get(1).mCerts,
- digestFromV4, result);
+ digestFromV41, result);
}
} else if (result.isVerifiedUsingV2Scheme()) {
if (v4Signers.size() != 1) {
@@ -543,7 +559,8 @@ public class ApkVerifier {
final byte[] digestFromV2 = pickBestDigestForV4(
v2Signers.get(0).getContentDigests());
if (!Arrays.equals(digestFromV4, digestFromV2)) {
- result.addError(Issue.V4_SIG_V2_V3_DIGESTS_MISMATCH);
+ result.addError(Issue.V4_SIG_V2_V3_DIGESTS_MISMATCH, 2, toHex(digestFromV2),
+ toHex(digestFromV4));
}
} else {
throw new RuntimeException("V4 signature must be also verified with V2/V3");
@@ -1135,7 +1152,8 @@ public class ApkVerifier {
// Compare digests.
final byte[] digestFromV3 = pickBestDigestForV4(v3Signers.get(0).getContentDigests());
if (!Arrays.equals(digestFromV4, digestFromV3)) {
- result.addError(Issue.V4_SIG_V2_V3_DIGESTS_MISMATCH);
+ result.addError(Issue.V4_SIG_V2_V3_DIGESTS_MISMATCH, 3, toHex(digestFromV3),
+ toHex(digestFromV4));
}
}
@@ -3124,14 +3142,40 @@ public class ApkVerifier {
"V4 signature only supports one signer"),
/**
+ * V4.1 signature requires two signers to match the v3 and the v3.1.
+ */
+ V41_SIG_NEEDS_TWO_SIGNERS("V4.1 signature requires two signers"),
+
+ /**
* The signer used to sign APK Signature Scheme V2/V3 signature does not match the signer
* used to sign APK Signature Scheme V4 signature.
*/
V4_SIG_V2_V3_SIGNERS_MISMATCH(
"V4 signature and V2/V3 signature have mismatched certificates"),
+ /**
+ * The v4 signature's digest does not match the digest from the corresponding v2 / v3
+ * signature.
+ *
+ * <ul>
+ * <li>Parameter 1: Signature scheme of mismatched digest ({@code int})
+ * <li>Parameter 2: v2/v3 digest ({@code String})
+ * <li>Parameter 3: v4 digest ({@code String})
+ * </ul>
+ */
V4_SIG_V2_V3_DIGESTS_MISMATCH(
- "V4 signature and V2/V3 signature have mismatched digests"),
+ "V4 signature and V%1$d signature have mismatched digests, V%1$d digest: %2$s, V4"
+ + " digest: %3$s"),
+
+ /**
+ * The v4 signature does not contain the expected number of digests.
+ *
+ * <ul>
+ * <li>Parameter 1: Number of digests found ({@code int})
+ * </ul>
+ */
+ V4_SIG_UNEXPECTED_DIGESTS(
+ "V4 signature does not have the expected number of digests, found %1$d"),
/**
* The v4 signature format version isn't the same as the tool's current version, something