Loading core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +2 −2 Original line number Diff line number Diff line Loading @@ -410,7 +410,7 @@ public class ApkSignatureSchemeV2Verifier { NoSuchAlgorithmException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { SignatureInfo signatureInfo = findSignature(apk); return ApkVerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo); return VerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo); } } Loading @@ -423,7 +423,7 @@ public class ApkSignatureSchemeV2Verifier { if (vSigner.verityRootHash == null) { return null; } return ApkVerityBuilder.generateApkVerityRootHash( return VerityBuilder.generateApkVerityRootHash( apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); } } Loading core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +2 −2 Original line number Diff line number Diff line Loading @@ -534,7 +534,7 @@ public class ApkSignatureSchemeV3Verifier { NoSuchAlgorithmException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { SignatureInfo signatureInfo = findSignature(apk); return ApkVerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo); return VerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo); } } Loading @@ -547,7 +547,7 @@ public class ApkSignatureSchemeV3Verifier { if (vSigner.verityRootHash == null) { return null; } return ApkVerityBuilder.generateApkVerityRootHash( return VerityBuilder.generateApkVerityRootHash( apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); } } Loading core/java/android/util/apk/ApkSigningBlockUtils.java +1 −1 Original line number Diff line number Diff line Loading @@ -332,7 +332,7 @@ final class ApkSigningBlockUtils { try { byte[] expectedRootHash = parseVerityDigestAndVerifySourceLength(expectedDigest, apk.length(), signatureInfo); ApkVerityBuilder.ApkVerityResult verity = ApkVerityBuilder.generateApkVerityTree(apk, VerityBuilder.VerityResult verity = VerityBuilder.generateApkVerityTree(apk, signatureInfo, new ByteBufferFactory() { @Override public ByteBuffer create(int capacity) { Loading core/java/android/util/apk/ApkVerityBuilder.java→core/java/android/util/apk/VerityBuilder.java +20 −20 Original line number Diff line number Diff line Loading @@ -29,19 +29,18 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; /** * ApkVerityBuilder builds the APK verity tree and the verity header. The generated tree format can * be stored on disk for apk-verity setup and used by kernel. Note that since the current * implementation is different from the upstream, we call this implementation apk-verity instead of * fs-verity. * VerityBuilder builds the verity Merkle tree and other metadata. The generated tree format can * be stored on disk for fs-verity setup and used by kernel. The builder support standard * fs-verity, and Android specific apk-verity that requires additional kernel patches. * * <p>Unlike a regular Merkle tree, APK verity tree does not cover the content fully. Due to * the existing APK format, it has to skip APK Signing Block and also has some special treatment for * the "Central Directory offset" field of ZIP End of Central Directory. * <p>Unlike a regular Merkle tree of fs-verity, the apk-verity tree does not cover the file content * fully, and has to skip APK Signing Block with some special treatment for the "Central Directory * offset" field of ZIP End of Central Directory. * * @hide */ public abstract class ApkVerityBuilder { private ApkVerityBuilder() {} public abstract class VerityBuilder { private VerityBuilder() {} private static final int CHUNK_SIZE_BYTES = 4096; // Typical Linux block size private static final int DIGEST_SIZE_BYTES = 32; // SHA-256 size Loading @@ -52,7 +51,7 @@ public abstract class ApkVerityBuilder { private static final byte[] DEFAULT_SALT = new byte[8]; /** Result generated by the builder. */ public static class ApkVerityResult { public static class VerityResult { /** Raw fs-verity metadata and Merkle tree ready to be deployed on disk. */ public final ByteBuffer verityData; Loading @@ -62,7 +61,7 @@ public abstract class ApkVerityBuilder { /** Root hash of the Merkle tree. */ public final byte[] rootHash; private ApkVerityResult(ByteBuffer verityData, int merkleTreeSize, byte[] rootHash) { private VerityResult(ByteBuffer verityData, int merkleTreeSize, byte[] rootHash) { this.verityData = verityData; this.merkleTreeSize = merkleTreeSize; this.rootHash = rootHash; Loading @@ -74,14 +73,14 @@ public abstract class ApkVerityBuilder { * ByteBuffer} created by the {@link ByteBufferFactory}. The output is suitable to be used as * the on-disk format for fs-verity to use. * * @return ApkVerityResult containing a buffer with the generated Merkle tree stored at the * @return VerityResult containing a buffer with the generated Merkle tree stored at the * front, the tree size, and the calculated root hash. */ @NonNull public static ApkVerityResult generateFsVerityTree(@NonNull RandomAccessFile apk, public static VerityResult generateFsVerityTree(@NonNull RandomAccessFile apk, @NonNull ByteBufferFactory bufferFactory) throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { return generateVerityTree(apk, bufferFactory, null /* signatureInfo */, return generateVerityTreeInternal(apk, bufferFactory, null /* signatureInfo */, false /* skipSigningBlock */); } Loading @@ -91,18 +90,19 @@ public abstract class ApkVerityBuilder { * Block specificed in {@code signatureInfo}. The output is suitable to be used as the on-disk * format for fs-verity to use (with elide and patch extensions). * * @return ApkVerityResult containing a buffer with the generated Merkle tree stored at the * @return VerityResult containing a buffer with the generated Merkle tree stored at the * front, the tree size, and the calculated root hash. */ @NonNull public static ApkVerityResult generateApkVerityTree(@NonNull RandomAccessFile apk, public static VerityResult generateApkVerityTree(@NonNull RandomAccessFile apk, @Nullable SignatureInfo signatureInfo, @NonNull ByteBufferFactory bufferFactory) throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { return generateVerityTree(apk, bufferFactory, signatureInfo, true /* skipSigningBlock */); return generateVerityTreeInternal(apk, bufferFactory, signatureInfo, true /* skipSigningBlock */); } @NonNull private static ApkVerityResult generateVerityTree(@NonNull RandomAccessFile apk, private static VerityResult generateVerityTreeInternal(@NonNull RandomAccessFile apk, @NonNull ByteBufferFactory bufferFactory, @Nullable SignatureInfo signatureInfo, boolean skipSigningBlock) throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { Loading @@ -124,7 +124,7 @@ public abstract class ApkVerityBuilder { byte[] salt = skipSigningBlock ? DEFAULT_SALT : null; byte[] apkRootHash = generateVerityTreeInternal(apk, signatureInfo, salt, levelOffset, tree, skipSigningBlock); return new ApkVerityResult(output, merkleTreeSize, apkRootHash); return new VerityResult(output, merkleTreeSize, apkRootHash); } static void generateApkVerityFooter(@NonNull RandomAccessFile apk, Loading Loading @@ -173,7 +173,7 @@ public abstract class ApkVerityBuilder { throws IOException, SignatureNotFoundException, SecurityException, DigestException, NoSuchAlgorithmException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { ApkVerityResult result = generateVerityTree(apk, bufferFactory, signatureInfo, VerityResult result = generateVerityTreeInternal(apk, bufferFactory, signatureInfo, true /* skipSigningBlock */); ByteBuffer footer = slice(result.verityData, result.merkleTreeSize, result.verityData.limit()); Loading services/core/java/com/android/server/pm/PackageManagerService.java +3 −2 Original line number Diff line number Diff line Loading @@ -8474,7 +8474,7 @@ public class PackageManagerService extends IPackageManager.Stub private boolean canSkipFullApkVerification(String apkPath) { final byte[] rootHashObserved; try { rootHashObserved = VerityUtils.generateFsverityRootHash(apkPath); rootHashObserved = VerityUtils.generateApkVerityRootHash(apkPath); if (rootHashObserved == null) { return false; // APK does not contain Merkle tree root hash. } Loading Loading @@ -16010,7 +16010,8 @@ public class PackageManagerService extends IPackageManager.Stub if (Build.IS_DEBUGGABLE) Slog.i(TAG, "Enabling apk verity to " + apkPath); FileDescriptor fd = result.getUnownedFileDescriptor(); try { final byte[] signedRootHash = VerityUtils.generateFsverityRootHash(apkPath); final byte[] signedRootHash = VerityUtils.generateApkVerityRootHash(apkPath); mInstaller.installApkVerity(apkPath, fd, result.getContentSize()); mInstaller.assertFsverityRootHashMatches(apkPath, signedRootHash); } catch (InstallerException | IOException | DigestException | Loading
core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +2 −2 Original line number Diff line number Diff line Loading @@ -410,7 +410,7 @@ public class ApkSignatureSchemeV2Verifier { NoSuchAlgorithmException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { SignatureInfo signatureInfo = findSignature(apk); return ApkVerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo); return VerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo); } } Loading @@ -423,7 +423,7 @@ public class ApkSignatureSchemeV2Verifier { if (vSigner.verityRootHash == null) { return null; } return ApkVerityBuilder.generateApkVerityRootHash( return VerityBuilder.generateApkVerityRootHash( apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); } } Loading
core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +2 −2 Original line number Diff line number Diff line Loading @@ -534,7 +534,7 @@ public class ApkSignatureSchemeV3Verifier { NoSuchAlgorithmException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { SignatureInfo signatureInfo = findSignature(apk); return ApkVerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo); return VerityBuilder.generateApkVerity(apkPath, bufferFactory, signatureInfo); } } Loading @@ -547,7 +547,7 @@ public class ApkSignatureSchemeV3Verifier { if (vSigner.verityRootHash == null) { return null; } return ApkVerityBuilder.generateApkVerityRootHash( return VerityBuilder.generateApkVerityRootHash( apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); } } Loading
core/java/android/util/apk/ApkSigningBlockUtils.java +1 −1 Original line number Diff line number Diff line Loading @@ -332,7 +332,7 @@ final class ApkSigningBlockUtils { try { byte[] expectedRootHash = parseVerityDigestAndVerifySourceLength(expectedDigest, apk.length(), signatureInfo); ApkVerityBuilder.ApkVerityResult verity = ApkVerityBuilder.generateApkVerityTree(apk, VerityBuilder.VerityResult verity = VerityBuilder.generateApkVerityTree(apk, signatureInfo, new ByteBufferFactory() { @Override public ByteBuffer create(int capacity) { Loading
core/java/android/util/apk/ApkVerityBuilder.java→core/java/android/util/apk/VerityBuilder.java +20 −20 Original line number Diff line number Diff line Loading @@ -29,19 +29,18 @@ import java.security.NoSuchAlgorithmException; import java.util.ArrayList; /** * ApkVerityBuilder builds the APK verity tree and the verity header. The generated tree format can * be stored on disk for apk-verity setup and used by kernel. Note that since the current * implementation is different from the upstream, we call this implementation apk-verity instead of * fs-verity. * VerityBuilder builds the verity Merkle tree and other metadata. The generated tree format can * be stored on disk for fs-verity setup and used by kernel. The builder support standard * fs-verity, and Android specific apk-verity that requires additional kernel patches. * * <p>Unlike a regular Merkle tree, APK verity tree does not cover the content fully. Due to * the existing APK format, it has to skip APK Signing Block and also has some special treatment for * the "Central Directory offset" field of ZIP End of Central Directory. * <p>Unlike a regular Merkle tree of fs-verity, the apk-verity tree does not cover the file content * fully, and has to skip APK Signing Block with some special treatment for the "Central Directory * offset" field of ZIP End of Central Directory. * * @hide */ public abstract class ApkVerityBuilder { private ApkVerityBuilder() {} public abstract class VerityBuilder { private VerityBuilder() {} private static final int CHUNK_SIZE_BYTES = 4096; // Typical Linux block size private static final int DIGEST_SIZE_BYTES = 32; // SHA-256 size Loading @@ -52,7 +51,7 @@ public abstract class ApkVerityBuilder { private static final byte[] DEFAULT_SALT = new byte[8]; /** Result generated by the builder. */ public static class ApkVerityResult { public static class VerityResult { /** Raw fs-verity metadata and Merkle tree ready to be deployed on disk. */ public final ByteBuffer verityData; Loading @@ -62,7 +61,7 @@ public abstract class ApkVerityBuilder { /** Root hash of the Merkle tree. */ public final byte[] rootHash; private ApkVerityResult(ByteBuffer verityData, int merkleTreeSize, byte[] rootHash) { private VerityResult(ByteBuffer verityData, int merkleTreeSize, byte[] rootHash) { this.verityData = verityData; this.merkleTreeSize = merkleTreeSize; this.rootHash = rootHash; Loading @@ -74,14 +73,14 @@ public abstract class ApkVerityBuilder { * ByteBuffer} created by the {@link ByteBufferFactory}. The output is suitable to be used as * the on-disk format for fs-verity to use. * * @return ApkVerityResult containing a buffer with the generated Merkle tree stored at the * @return VerityResult containing a buffer with the generated Merkle tree stored at the * front, the tree size, and the calculated root hash. */ @NonNull public static ApkVerityResult generateFsVerityTree(@NonNull RandomAccessFile apk, public static VerityResult generateFsVerityTree(@NonNull RandomAccessFile apk, @NonNull ByteBufferFactory bufferFactory) throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { return generateVerityTree(apk, bufferFactory, null /* signatureInfo */, return generateVerityTreeInternal(apk, bufferFactory, null /* signatureInfo */, false /* skipSigningBlock */); } Loading @@ -91,18 +90,19 @@ public abstract class ApkVerityBuilder { * Block specificed in {@code signatureInfo}. The output is suitable to be used as the on-disk * format for fs-verity to use (with elide and patch extensions). * * @return ApkVerityResult containing a buffer with the generated Merkle tree stored at the * @return VerityResult containing a buffer with the generated Merkle tree stored at the * front, the tree size, and the calculated root hash. */ @NonNull public static ApkVerityResult generateApkVerityTree(@NonNull RandomAccessFile apk, public static VerityResult generateApkVerityTree(@NonNull RandomAccessFile apk, @Nullable SignatureInfo signatureInfo, @NonNull ByteBufferFactory bufferFactory) throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { return generateVerityTree(apk, bufferFactory, signatureInfo, true /* skipSigningBlock */); return generateVerityTreeInternal(apk, bufferFactory, signatureInfo, true /* skipSigningBlock */); } @NonNull private static ApkVerityResult generateVerityTree(@NonNull RandomAccessFile apk, private static VerityResult generateVerityTreeInternal(@NonNull RandomAccessFile apk, @NonNull ByteBufferFactory bufferFactory, @Nullable SignatureInfo signatureInfo, boolean skipSigningBlock) throws IOException, SecurityException, NoSuchAlgorithmException, DigestException { Loading @@ -124,7 +124,7 @@ public abstract class ApkVerityBuilder { byte[] salt = skipSigningBlock ? DEFAULT_SALT : null; byte[] apkRootHash = generateVerityTreeInternal(apk, signatureInfo, salt, levelOffset, tree, skipSigningBlock); return new ApkVerityResult(output, merkleTreeSize, apkRootHash); return new VerityResult(output, merkleTreeSize, apkRootHash); } static void generateApkVerityFooter(@NonNull RandomAccessFile apk, Loading Loading @@ -173,7 +173,7 @@ public abstract class ApkVerityBuilder { throws IOException, SignatureNotFoundException, SecurityException, DigestException, NoSuchAlgorithmException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { ApkVerityResult result = generateVerityTree(apk, bufferFactory, signatureInfo, VerityResult result = generateVerityTreeInternal(apk, bufferFactory, signatureInfo, true /* skipSigningBlock */); ByteBuffer footer = slice(result.verityData, result.merkleTreeSize, result.verityData.limit()); Loading
services/core/java/com/android/server/pm/PackageManagerService.java +3 −2 Original line number Diff line number Diff line Loading @@ -8474,7 +8474,7 @@ public class PackageManagerService extends IPackageManager.Stub private boolean canSkipFullApkVerification(String apkPath) { final byte[] rootHashObserved; try { rootHashObserved = VerityUtils.generateFsverityRootHash(apkPath); rootHashObserved = VerityUtils.generateApkVerityRootHash(apkPath); if (rootHashObserved == null) { return false; // APK does not contain Merkle tree root hash. } Loading Loading @@ -16010,7 +16010,8 @@ public class PackageManagerService extends IPackageManager.Stub if (Build.IS_DEBUGGABLE) Slog.i(TAG, "Enabling apk verity to " + apkPath); FileDescriptor fd = result.getUnownedFileDescriptor(); try { final byte[] signedRootHash = VerityUtils.generateFsverityRootHash(apkPath); final byte[] signedRootHash = VerityUtils.generateApkVerityRootHash(apkPath); mInstaller.installApkVerity(apkPath, fd, result.getContentSize()); mInstaller.assertFsverityRootHashMatches(apkPath, signedRootHash); } catch (InstallerException | IOException | DigestException |