Merge "Fallback to sha256 when preferred checksum failed"
diff --git a/core/java/android/util/PackageUtils.java b/core/java/android/util/PackageUtils.java
index 6f8c5db..ea7efc7 100644
--- a/core/java/android/util/PackageUtils.java
+++ b/core/java/android/util/PackageUtils.java
@@ -184,24 +184,15 @@
}
/**
- * @see #computeSha256DigestForLargeFile(String, byte[], String)
- */
- public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
- @NonNull byte[] fileBuffer) {
- return computeSha256DigestForLargeFile(filePath, fileBuffer, null);
- }
-
- /**
- * Computes the SHA256 digest of large files. This is typically useful for large APEXs.
+ * Computes the SHA256 digest of a large file.
* @param filePath The path to which the file's content is to be hashed.
* @param fileBuffer A buffer to read file's content into memory. It is strongly recommended to
* make use of the {@link #createLargeFileBuffer()} method to create this
* buffer.
- * @param separator Separator between each pair of characters, such as colon, or null to omit.
- * @return The SHA256 digest or null if an error occurs.
+ * @return The byte array of SHA256 digest or null if an error occurs.
*/
- public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
- @NonNull byte[] fileBuffer, @Nullable String separator) {
+ public static @Nullable byte[] computeSha256DigestForLargeFileAsBytes(@NonNull String filePath,
+ @NonNull byte[] fileBuffer) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("SHA256");
@@ -221,8 +212,30 @@
return null;
}
- byte[] resultBytes = messageDigest.digest();
+ return messageDigest.digest();
+ }
+ /**
+ * @see #computeSha256DigestForLargeFile(String, byte[], String)
+ */
+ public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
+ @NonNull byte[] fileBuffer) {
+ return computeSha256DigestForLargeFile(filePath, fileBuffer, null);
+ }
+
+ /**
+ * Computes the SHA256 digest of a large file.
+ * @param filePath The path to which the file's content is to be hashed.
+ * @param fileBuffer A buffer to read file's content into memory. It is strongly recommended to
+ * make use of the {@link #createLargeFileBuffer()} method to create this
+ * buffer.
+ * @param separator Separator between each pair of characters, such as colon, or null to omit.
+ * @see #computeSha256DigestForLargeFile(String, byte[])
+ * @return The encoded string of SHA256 digest or null if an error occurs.
+ */
+ public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
+ @NonNull byte[] fileBuffer, @Nullable String separator) {
+ byte[] resultBytes = computeSha256DigestForLargeFileAsBytes(filePath, fileBuffer);
if (separator == null) {
return HexEncoding.encodeToString(resultBytes, false);
}
diff --git a/services/core/java/com/android/server/BinaryTransparencyService.java b/services/core/java/com/android/server/BinaryTransparencyService.java
index eafd3e0..f49dfeb 100644
--- a/services/core/java/com/android/server/BinaryTransparencyService.java
+++ b/services/core/java/com/android/server/BinaryTransparencyService.java
@@ -263,26 +263,26 @@
Map<Integer, byte[]> contentDigests = computeApkContentDigest(apkPath);
if (contentDigests == null) {
Slog.d(TAG, "Failed to compute content digest for " + apkPath);
- return new Checksum(0, new byte[] { -1 });
- }
-
- // in this iteration, we'll be supporting only 2 types of digests:
- // CHUNKED_SHA256 and CHUNKED_SHA512.
- // And only one of them will be available per package.
- if (contentDigests.containsKey(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
- return new Checksum(
- Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
- contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
- } else if (contentDigests.containsKey(
- ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
- return new Checksum(
- Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
- contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
} else {
- // TODO(b/259423111): considering putting the raw values for the algorithm & digest
- // into the bundle to track potential other digest algorithms that may be in use
- return new Checksum(0, new byte[] { -1 });
+ // in this iteration, we'll be supporting only 2 types of digests:
+ // CHUNKED_SHA256 and CHUNKED_SHA512.
+ // And only one of them will be available per package.
+ if (contentDigests.containsKey(
+ ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256)) {
+ return new Checksum(
+ Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256,
+ contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA256));
+ } else if (contentDigests.containsKey(
+ ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512)) {
+ return new Checksum(
+ Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512,
+ contentDigests.get(ApkSigningBlockUtils.CONTENT_DIGEST_CHUNKED_SHA512));
+ }
}
+ // When something went wrong, fall back to simple sha256.
+ byte[] digest = PackageUtils.computeSha256DigestForLargeFileAsBytes(apkPath,
+ PackageUtils.createLargeFileBuffer());
+ return new Checksum(Checksum.TYPE_WHOLE_SHA256, digest);
}