Fallback to sha256 when preferred checksum failed

Bug: 265467404
Test: Manually remove the signing block of an updated preload, run the
      job.  Saw a local debugging log of sha256 measurement.
Change-Id: I8a4de6ce01a5bfc0c021ece6dbb6efffce9eba25
This commit is contained in:
Victor Hsieh
2023-02-10 10:29:05 -08:00
parent 35b1662ea3
commit 8b7cc7fbed
2 changed files with 45 additions and 32 deletions

View File

@@ -184,24 +184,15 @@ public final class PackageUtils {
}
/**
* @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 @@ public final class PackageUtils {
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);
}

View File

@@ -263,26 +263,26 @@ public class BinaryTransparencyService extends SystemService {
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);
}