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

Commit 3a0032f3 authored by Victor Hsieh's avatar Victor Hsieh
Browse files

Change verity hash algorithm to pad the last chunk

As the result, all existing cases takes complete chunk for hashing.

Also bump to version number.

Test: without also bumping the version, apk with 0x401 hash won't install
Test: apk with 0x411 hash installs
Bug: 30972906
Change-Id: I48c15c886ac6eab4512f1b2b9744b07e746c6211
parent b23e1716
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -373,9 +373,9 @@ final class ApkSigningBlockUtils {
    static final int SIGNATURE_ECDSA_WITH_SHA256 = 0x0201;
    static final int SIGNATURE_ECDSA_WITH_SHA512 = 0x0202;
    static final int SIGNATURE_DSA_WITH_SHA256 = 0x0301;
    static final int SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 = 0x0401;
    static final int SIGNATURE_VERITY_ECDSA_WITH_SHA256 = 0x0403;
    static final int SIGNATURE_VERITY_DSA_WITH_SHA256 = 0x0405;
    static final int SIGNATURE_VERITY_RSA_PKCS1_V1_5_WITH_SHA256 = 0x0411;
    static final int SIGNATURE_VERITY_ECDSA_WITH_SHA256 = 0x0413;
    static final int SIGNATURE_VERITY_DSA_WITH_SHA256 = 0x0415;

    static final int CONTENT_DIGEST_CHUNKED_SHA256 = 1;
    static final int CONTENT_DIGEST_CHUNKED_SHA512 = 2;
@@ -754,9 +754,6 @@ final class ApkSigningBlockUtils {
                md.update(buffer);
            }
        }

        @Override
        public void finish() {}
    }

}
+13 −12
Original line number Diff line number Diff line
@@ -207,14 +207,10 @@ abstract class ApkVerityBuilder {
            }
        }

        /** Finish the current digestion if any. */
        @Override
        public void finish() throws DigestException {
            if (mBytesDigestedSinceReset == 0) {
                return;
        public void assertEmptyBuffer() throws DigestException {
            if (mBytesDigestedSinceReset != 0) {
                throw new IllegalStateException("Buffer is not empty: " + mBytesDigestedSinceReset);
            }
            mMd.digest(mDigestBuffer, 0, mDigestBuffer.length);
            mOutput.put(mDigestBuffer);
        }

        private void fillUpLastOutputChunk() {
@@ -279,9 +275,15 @@ abstract class ApkVerityBuilder {
                new MemoryMappedFileDataSource(apk.getFD(), offsetAfterEocdCdOffsetField,
                    apk.length() - offsetAfterEocdCdOffsetField),
                MMAP_REGION_SIZE_BYTES);
        digester.finish();

        // 5. Fill up the rest of buffer with 0s.
        // 5. Pad 0s up to the nearest 4096-byte block before hashing.
        int lastIncompleteChunkSize = (int) (apk.length() % CHUNK_SIZE_BYTES);
        if (lastIncompleteChunkSize != 0) {
            digester.consume(ByteBuffer.allocate(CHUNK_SIZE_BYTES - lastIncompleteChunkSize));
        }
        digester.assertEmptyBuffer();

        // 6. Fill up the rest of buffer with 0s.
        digester.fillUpLastOutputChunk();
    }

@@ -300,8 +302,7 @@ abstract class ApkVerityBuilder {
            DataSource source = new ByteBufferDataSource(inputBuffer);
            BufferedDigester digester = new BufferedDigester(salt, outputBuffer);
            consumeByChunk(digester, source, CHUNK_SIZE_BYTES);
            digester.finish();

            digester.assertEmptyBuffer();
            digester.fillUpLastOutputChunk();
        }

@@ -309,7 +310,7 @@ abstract class ApkVerityBuilder {
        byte[] rootHash = new byte[DIGEST_SIZE_BYTES];
        BufferedDigester digester = new BufferedDigester(salt, ByteBuffer.wrap(rootHash));
        digester.consume(slice(output, 0, CHUNK_SIZE_BYTES));
        digester.finish();
        digester.assertEmptyBuffer();
        return rootHash;
    }

+0 −3
Original line number Diff line number Diff line
@@ -22,7 +22,4 @@ import java.security.DigestException;
interface DataDigester {
    /** Consumes the {@link ByteBuffer}. */
    void consume(ByteBuffer buffer) throws DigestException;

    /** Finishes the digestion. Must be called after the last {@link #consume(ByteBuffer)}. */
    void finish() throws DigestException;
}