From c65e303681374fb73edf171c89fc670c9b6cd9cd Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Fri, 30 Jul 2021 13:49:14 +0900 Subject: [PATCH] APK signature verification: use FileChannel#size RandomAccessFile#length returns 0 for block devices while FileChannel#size returns the correct size. APK signature verification utils should work with block-device zip files when Android is running as a guest OS and APK/APEX files are passed via block devices. This is a follow-up of 1257f1505cb2ac75b6959e16d195c7c4bac8ee06. Bug: 193592496 Bug: 192366904 Test: FrameworksServicesTests Merged-In: I3015fc30574c36c18c0d0c9ae7453d33a1349927 Change-Id: I3015fc30574c36c18c0d0c9ae7453d33a1349927 (cherry picked from commit 310edbe3c7202581bf10b6a621a287b297d73261) --- .../android/util/apk/ApkSignatureSchemeV2Verifier.java | 2 +- .../android/util/apk/ApkSignatureSchemeV3Verifier.java | 2 +- core/java/android/util/apk/ApkSigningBlockUtils.java | 2 +- core/java/android/util/apk/VerityBuilder.java | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java index 346fe293d7aee..0771157693742 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java @@ -210,7 +210,7 @@ public class ApkSignatureSchemeV2Verifier { if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) { byte[] verityDigest = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256); verityRootHash = ApkSigningBlockUtils.parseVerityDigestAndVerifySourceLength( - verityDigest, apk.length(), signatureInfo); + verityDigest, apk.getChannel().size(), signatureInfo); } byte[] digest = pickBestDigestForV4(contentDigests); diff --git a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java index 4ab541b616ed4..44f01a4f9759c 100644 --- a/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +++ b/core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java @@ -209,7 +209,7 @@ public class ApkSignatureSchemeV3Verifier { if (contentDigests.containsKey(CONTENT_DIGEST_VERITY_CHUNKED_SHA256)) { byte[] verityDigest = contentDigests.get(CONTENT_DIGEST_VERITY_CHUNKED_SHA256); result.verityRootHash = ApkSigningBlockUtils.parseVerityDigestAndVerifySourceLength( - verityDigest, apk.length(), signatureInfo); + verityDigest, apk.getChannel().size(), signatureInfo); } result.digest = pickBestDigestForV4(contentDigests); diff --git a/core/java/android/util/apk/ApkSigningBlockUtils.java b/core/java/android/util/apk/ApkSigningBlockUtils.java index 6efe95cb9e92d..f79b5b99b7e6a 100644 --- a/core/java/android/util/apk/ApkSigningBlockUtils.java +++ b/core/java/android/util/apk/ApkSigningBlockUtils.java @@ -349,7 +349,7 @@ final class ApkSigningBlockUtils { SignatureInfo signatureInfo) throws SecurityException { try { byte[] expectedRootHash = parseVerityDigestAndVerifySourceLength(expectedDigest, - apk.length(), signatureInfo); + apk.getChannel().size(), signatureInfo); VerityBuilder.VerityResult verity = VerityBuilder.generateApkVerityTree(apk, signatureInfo, new ByteBufferFactory() { @Override diff --git a/core/java/android/util/apk/VerityBuilder.java b/core/java/android/util/apk/VerityBuilder.java index e81e3f7b38d6a..3dfa4cd1a0d2c 100644 --- a/core/java/android/util/apk/VerityBuilder.java +++ b/core/java/android/util/apk/VerityBuilder.java @@ -90,7 +90,7 @@ public abstract class VerityBuilder { throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { long signingBlockSize = signatureInfo.centralDirOffset - signatureInfo.apkSigningBlockOffset; - long dataSize = apk.length() - signingBlockSize; + long dataSize = apk.getChannel().size() - signingBlockSize; int[] levelOffset = calculateVerityLevelOffset(dataSize); int merkleTreeSize = levelOffset[levelOffset.length - 1]; @@ -108,7 +108,7 @@ public abstract class VerityBuilder { @NonNull SignatureInfo signatureInfo, @NonNull ByteBuffer footerOutput) throws IOException { footerOutput.order(ByteOrder.LITTLE_ENDIAN); - generateApkVerityHeader(footerOutput, apk.length(), DEFAULT_SALT); + generateApkVerityHeader(footerOutput, apk.getChannel().size(), DEFAULT_SALT); long signingBlockSize = signatureInfo.centralDirOffset - signatureInfo.apkSigningBlockOffset; generateApkVerityExtensions(footerOutput, signatureInfo.apkSigningBlockOffset, @@ -310,11 +310,11 @@ public abstract class VerityBuilder { eocdCdOffsetFieldPosition + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_SIZE; consumeByChunk(digester, new MemoryMappedFileDataSource(apk.getFD(), offsetAfterEocdCdOffsetField, - apk.length() - offsetAfterEocdCdOffsetField), + apk.getChannel().size() - offsetAfterEocdCdOffsetField), MMAP_REGION_SIZE_BYTES); // 5. Pad 0s up to the nearest 4096-byte block before hashing. - int lastIncompleteChunkSize = (int) (apk.length() % CHUNK_SIZE_BYTES); + int lastIncompleteChunkSize = (int) (apk.getChannel().size() % CHUNK_SIZE_BYTES); if (lastIncompleteChunkSize != 0) { digester.consume(ByteBuffer.allocate(CHUNK_SIZE_BYTES - lastIncompleteChunkSize)); }