Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 310edbe3 authored by Jooyung Han's avatar Jooyung Han
Browse files

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 1257f150.

Bug: 193592496
Bug: 192366904
Test: FrameworksServicesTests
Change-Id: I3015fc30574c36c18c0d0c9ae7453d33a1349927
parent c841e1fd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -209,7 +209,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);
        }

        return new VerifiedSigner(
+1 −1
Original line number Diff line number Diff line
@@ -211,7 +211,7 @@ public class ApkSignatureSchemeV3Verifier {
        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);
        }

        return new VerifiedSigner(result.first, result.second, verityRootHash, contentDigests);
+1 −1
Original line number Diff line number Diff line
@@ -368,7 +368,7 @@ public 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
+4 −4
Original line number Diff line number Diff line
@@ -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,
@@ -339,11 +339,11 @@ public abstract class VerityBuilder {
                eocdCdOffsetFieldPosition + ZIP_EOCD_CENTRAL_DIR_OFFSET_FIELD_SIZE;
        consumeByChunk(digester,
                DataSource.create(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));
        }