OSDN Git Service

Change verity hash algorithm to pad the last chunk
authorVictor Hsieh <victorhsieh@google.com>
Tue, 20 Feb 2018 23:22:28 +0000 (15:22 -0800)
committerVictor Hsieh <victorhsieh@google.com>
Tue, 20 Feb 2018 23:34:46 +0000 (15:34 -0800)
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

core/java/android/util/apk/ApkSigningBlockUtils.java
core/java/android/util/apk/ApkVerityBuilder.java
core/java/android/util/apk/DataDigester.java

index 4146f6f..40db758 100644 (file)
@@ -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() {}
     }
 
 }
index a3eeb27..7b89967 100644 (file)
@@ -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;
     }
 
index 278be80..18d1dff 100644 (file)
@@ -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;
 }