Loading core/java/android/util/apk/ApkVerityBuilder.java +16 −13 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.security.DigestException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; Loading Loading @@ -66,7 +67,7 @@ abstract class ApkVerityBuilder { */ static ApkVerityResult generateApkVerity(RandomAccessFile apk, SignatureInfo signatureInfo, ByteBufferFactory bufferFactory) throws IOException, SecurityException, NoSuchAlgorithmException { throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { assertSigningBlockAlignedAndHasFullPages(signatureInfo); long signingBlockSize = Loading Loading @@ -112,6 +113,7 @@ abstract class ApkVerityBuilder { private final ByteBuffer mOutput; private final MessageDigest mMd; private final byte[] mDigestBuffer = new byte[DIGEST_SIZE_BYTES]; private final byte[] mSalt; private BufferedDigester(byte[] salt, ByteBuffer output) throws NoSuchAlgorithmException { Loading @@ -129,21 +131,22 @@ abstract class ApkVerityBuilder { * consumption will continuous from there. */ @Override public void consume(ByteBuffer buffer) { public void consume(ByteBuffer buffer) throws DigestException { int offset = buffer.position(); int remaining = buffer.remaining(); while (remaining > 0) { int allowance = (int) Math.min(remaining, BUFFER_SIZE - mBytesDigestedSinceReset); mMd.update(slice(buffer, offset, offset + allowance)); // Optimization: set the buffer limit to avoid allocating a new ByteBuffer object. buffer.limit(buffer.position() + allowance); mMd.update(buffer); offset += allowance; remaining -= allowance; mBytesDigestedSinceReset += allowance; if (mBytesDigestedSinceReset == BUFFER_SIZE) { byte[] digest = mMd.digest(); mOutput.put(digest); mMd.reset(); mMd.digest(mDigestBuffer, 0, mDigestBuffer.length); mOutput.put(mDigestBuffer); // After digest, MessageDigest resets automatically, so no need to reset again. mMd.update(mSalt); mBytesDigestedSinceReset = 0; } Loading @@ -152,12 +155,12 @@ abstract class ApkVerityBuilder { /** Finish the current digestion if any. */ @Override public void finish() { public void finish() throws DigestException { if (mBytesDigestedSinceReset == 0) { return; } byte[] digest = mMd.digest(); mOutput.put(digest); mMd.digest(mDigestBuffer, 0, mDigestBuffer.length); mOutput.put(mDigestBuffer); } private void fillUpLastOutputChunk() { Loading @@ -174,7 +177,7 @@ abstract class ApkVerityBuilder { * digest the remaining. */ private static void consumeByChunk(DataDigester digester, DataSource source, int chunkSize) throws IOException { throws IOException, DigestException { long inputRemaining = source.size(); long inputOffset = 0; while (inputRemaining > 0) { Loading @@ -191,7 +194,7 @@ abstract class ApkVerityBuilder { private static void generateApkVerityDigestAtLeafLevel(RandomAccessFile apk, SignatureInfo signatureInfo, byte[] salt, ByteBuffer output) throws IOException, NoSuchAlgorithmException { throws IOException, NoSuchAlgorithmException, DigestException { BufferedDigester digester = new BufferedDigester(salt, output); // 1. Digest from the beginning of the file, until APK Signing Block is reached. Loading Loading @@ -230,7 +233,7 @@ abstract class ApkVerityBuilder { private static byte[] generateApkVerityTree(RandomAccessFile apk, SignatureInfo signatureInfo, byte[] salt, int[] levelOffset, ByteBuffer output) throws IOException, NoSuchAlgorithmException { throws IOException, NoSuchAlgorithmException, DigestException { // 1. Digest the apk to generate the leaf level hashes. generateApkVerityDigestAtLeafLevel(apk, signatureInfo, salt, slice(output, levelOffset[levelOffset.length - 2], levelOffset[levelOffset.length - 1])); Loading core/java/android/util/apk/ByteBufferDataSource.java +2 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.util.apk; import java.io.IOException; import java.nio.ByteBuffer; import java.security.DigestException; /** * {@link DataSource} which provides data from a {@link ByteBuffer}. Loading @@ -42,7 +43,7 @@ class ByteBufferDataSource implements DataSource { @Override public void feedIntoDataDigester(DataDigester md, long offset, int size) throws IOException { throws IOException, DigestException { // There's no way to tell MessageDigest to read data from ByteBuffer from a position // other than the buffer's current position. We thus need to change the buffer's // position to match the requested offset. Loading core/java/android/util/apk/DataDigester.java +3 −2 Original line number Diff line number Diff line Loading @@ -17,11 +17,12 @@ package android.util.apk; import java.nio.ByteBuffer; import java.security.DigestException; interface DataDigester { /** Consumes the {@link ByteBuffer}. */ void consume(ByteBuffer buffer); void consume(ByteBuffer buffer) throws DigestException; /** Finishes the digestion. Must be called after the last {@link #consume(ByteBuffer)}. */ void finish(); void finish() throws DigestException; } core/java/android/util/apk/DataSource.java +3 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.util.apk; import java.io.IOException; import java.security.DigestException; /** Source of data to be digested. */ interface DataSource { Loading @@ -32,5 +33,6 @@ interface DataSource { * @param offset offset of the region inside this data source. * @param size size (in bytes) of the region. */ void feedIntoDataDigester(DataDigester md, long offset, int size) throws IOException; void feedIntoDataDigester(DataDigester md, long offset, int size) throws IOException, DigestException; } core/java/android/util/apk/MemoryMappedFileDataSource.java +2 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.DirectByteBuffer; import java.security.DigestException; /** * {@link DataSource} which provides data from a file descriptor by memory-mapping the sections Loading Loading @@ -55,7 +56,7 @@ class MemoryMappedFileDataSource implements DataSource { @Override public void feedIntoDataDigester(DataDigester md, long offset, int size) throws IOException { throws IOException, DigestException { // IMPLEMENTATION NOTE: After a lot of experimentation, the implementation of this // method was settled on a straightforward mmap with prefaulting. // Loading Loading
core/java/android/util/apk/ApkVerityBuilder.java +16 −13 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.security.DigestException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; Loading Loading @@ -66,7 +67,7 @@ abstract class ApkVerityBuilder { */ static ApkVerityResult generateApkVerity(RandomAccessFile apk, SignatureInfo signatureInfo, ByteBufferFactory bufferFactory) throws IOException, SecurityException, NoSuchAlgorithmException { throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { assertSigningBlockAlignedAndHasFullPages(signatureInfo); long signingBlockSize = Loading Loading @@ -112,6 +113,7 @@ abstract class ApkVerityBuilder { private final ByteBuffer mOutput; private final MessageDigest mMd; private final byte[] mDigestBuffer = new byte[DIGEST_SIZE_BYTES]; private final byte[] mSalt; private BufferedDigester(byte[] salt, ByteBuffer output) throws NoSuchAlgorithmException { Loading @@ -129,21 +131,22 @@ abstract class ApkVerityBuilder { * consumption will continuous from there. */ @Override public void consume(ByteBuffer buffer) { public void consume(ByteBuffer buffer) throws DigestException { int offset = buffer.position(); int remaining = buffer.remaining(); while (remaining > 0) { int allowance = (int) Math.min(remaining, BUFFER_SIZE - mBytesDigestedSinceReset); mMd.update(slice(buffer, offset, offset + allowance)); // Optimization: set the buffer limit to avoid allocating a new ByteBuffer object. buffer.limit(buffer.position() + allowance); mMd.update(buffer); offset += allowance; remaining -= allowance; mBytesDigestedSinceReset += allowance; if (mBytesDigestedSinceReset == BUFFER_SIZE) { byte[] digest = mMd.digest(); mOutput.put(digest); mMd.reset(); mMd.digest(mDigestBuffer, 0, mDigestBuffer.length); mOutput.put(mDigestBuffer); // After digest, MessageDigest resets automatically, so no need to reset again. mMd.update(mSalt); mBytesDigestedSinceReset = 0; } Loading @@ -152,12 +155,12 @@ abstract class ApkVerityBuilder { /** Finish the current digestion if any. */ @Override public void finish() { public void finish() throws DigestException { if (mBytesDigestedSinceReset == 0) { return; } byte[] digest = mMd.digest(); mOutput.put(digest); mMd.digest(mDigestBuffer, 0, mDigestBuffer.length); mOutput.put(mDigestBuffer); } private void fillUpLastOutputChunk() { Loading @@ -174,7 +177,7 @@ abstract class ApkVerityBuilder { * digest the remaining. */ private static void consumeByChunk(DataDigester digester, DataSource source, int chunkSize) throws IOException { throws IOException, DigestException { long inputRemaining = source.size(); long inputOffset = 0; while (inputRemaining > 0) { Loading @@ -191,7 +194,7 @@ abstract class ApkVerityBuilder { private static void generateApkVerityDigestAtLeafLevel(RandomAccessFile apk, SignatureInfo signatureInfo, byte[] salt, ByteBuffer output) throws IOException, NoSuchAlgorithmException { throws IOException, NoSuchAlgorithmException, DigestException { BufferedDigester digester = new BufferedDigester(salt, output); // 1. Digest from the beginning of the file, until APK Signing Block is reached. Loading Loading @@ -230,7 +233,7 @@ abstract class ApkVerityBuilder { private static byte[] generateApkVerityTree(RandomAccessFile apk, SignatureInfo signatureInfo, byte[] salt, int[] levelOffset, ByteBuffer output) throws IOException, NoSuchAlgorithmException { throws IOException, NoSuchAlgorithmException, DigestException { // 1. Digest the apk to generate the leaf level hashes. generateApkVerityDigestAtLeafLevel(apk, signatureInfo, salt, slice(output, levelOffset[levelOffset.length - 2], levelOffset[levelOffset.length - 1])); Loading
core/java/android/util/apk/ByteBufferDataSource.java +2 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.util.apk; import java.io.IOException; import java.nio.ByteBuffer; import java.security.DigestException; /** * {@link DataSource} which provides data from a {@link ByteBuffer}. Loading @@ -42,7 +43,7 @@ class ByteBufferDataSource implements DataSource { @Override public void feedIntoDataDigester(DataDigester md, long offset, int size) throws IOException { throws IOException, DigestException { // There's no way to tell MessageDigest to read data from ByteBuffer from a position // other than the buffer's current position. We thus need to change the buffer's // position to match the requested offset. Loading
core/java/android/util/apk/DataDigester.java +3 −2 Original line number Diff line number Diff line Loading @@ -17,11 +17,12 @@ package android.util.apk; import java.nio.ByteBuffer; import java.security.DigestException; interface DataDigester { /** Consumes the {@link ByteBuffer}. */ void consume(ByteBuffer buffer); void consume(ByteBuffer buffer) throws DigestException; /** Finishes the digestion. Must be called after the last {@link #consume(ByteBuffer)}. */ void finish(); void finish() throws DigestException; }
core/java/android/util/apk/DataSource.java +3 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.util.apk; import java.io.IOException; import java.security.DigestException; /** Source of data to be digested. */ interface DataSource { Loading @@ -32,5 +33,6 @@ interface DataSource { * @param offset offset of the region inside this data source. * @param size size (in bytes) of the region. */ void feedIntoDataDigester(DataDigester md, long offset, int size) throws IOException; void feedIntoDataDigester(DataDigester md, long offset, int size) throws IOException, DigestException; }
core/java/android/util/apk/MemoryMappedFileDataSource.java +2 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.DirectByteBuffer; import java.security.DigestException; /** * {@link DataSource} which provides data from a file descriptor by memory-mapping the sections Loading Loading @@ -55,7 +56,7 @@ class MemoryMappedFileDataSource implements DataSource { @Override public void feedIntoDataDigester(DataDigester md, long offset, int size) throws IOException { throws IOException, DigestException { // IMPLEMENTATION NOTE: After a lot of experimentation, the implementation of this // method was settled on a straightforward mmap with prefaulting. // Loading