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;
md.update(buffer);
}
}
-
- @Override
- public void finish() {}
}
}
}
}
- /** 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() {
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();
}
DataSource source = new ByteBufferDataSource(inputBuffer);
BufferedDigester digester = new BufferedDigester(salt, outputBuffer);
consumeByChunk(digester, source, CHUNK_SIZE_BYTES);
- digester.finish();
-
+ digester.assertEmptyBuffer();
digester.fillUpLastOutputChunk();
}
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;
}