Loading core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +0 −14 Original line number Diff line number Diff line Loading @@ -407,20 +407,6 @@ public class ApkSignatureSchemeV2Verifier { } } static byte[] generateApkVerityRootHash(String apkPath) throws IOException, SignatureNotFoundException, DigestException, NoSuchAlgorithmException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { SignatureInfo signatureInfo = findSignature(apk); VerifiedSigner vSigner = verify(apk, false); if (vSigner.verityRootHash == null) { return null; } return VerityBuilder.generateApkVerityRootHash( apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); } } /** * Verified APK Signature Scheme v2 signer. * Loading core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +0 −14 Original line number Diff line number Diff line Loading @@ -444,20 +444,6 @@ public class ApkSignatureSchemeV3Verifier { } } static byte[] generateApkVerityRootHash(String apkPath) throws NoSuchAlgorithmException, DigestException, IOException, SignatureNotFoundException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { SignatureInfo signatureInfo = findSignature(apk); VerifiedSigner vSigner = verify(apk, false); if (vSigner.verityRootHash == null) { return null; } return VerityBuilder.generateApkVerityRootHash( apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); } } /** * Verified APK Signature Scheme v3 signer, including the proof of rotation structure. * Loading core/java/android/util/apk/ApkSignatureVerifier.java +0 −21 Original line number Diff line number Diff line Loading @@ -550,27 +550,6 @@ public class ApkSignatureVerifier { return ApkSignatureSchemeV2Verifier.generateApkVerity(apkPath, bufferFactory); } /** * Generates the FSVerity root hash from FSVerity header, extensions and Merkle tree root hash * in Signing Block. * * @return FSverity root hash */ public static byte[] generateApkVerityRootHash(String apkPath) throws NoSuchAlgorithmException, DigestException, IOException { // first try v3 try { return ApkSignatureSchemeV3Verifier.generateApkVerityRootHash(apkPath); } catch (SignatureNotFoundException e) { // try older version } try { return ApkSignatureSchemeV2Verifier.generateApkVerityRootHash(apkPath); } catch (SignatureNotFoundException e) { return null; } } /** * Extended signing details. * @hide for internal use only. Loading core/java/android/util/apk/VerityBuilder.java +0 −19 Original line number Diff line number Diff line Loading @@ -143,25 +143,6 @@ public abstract class VerityBuilder { return generateFsVerityTreeInternal(apk, salt, levelOffset, tree); } } /** * Calculates the apk-verity root hash for integrity measurement. This needs to be consistent * to what kernel returns. */ @NonNull static byte[] generateApkVerityRootHash(@NonNull RandomAccessFile apk, @NonNull ByteBuffer apkDigest, @NonNull SignatureInfo signatureInfo) throws NoSuchAlgorithmException, DigestException, IOException { assertSigningBlockAlignedAndHasFullPages(signatureInfo); ByteBuffer footer = ByteBuffer.allocate(CHUNK_SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN); generateApkVerityFooter(apk, signatureInfo, footer); footer.flip(); MessageDigest md = MessageDigest.getInstance(JCA_DIGEST_ALGORITHM); md.update(footer); md.update(apkDigest); return md.digest(); } /** * Generates the apk-verity header and hash tree to be used by kernel for the given apk. This Loading core/java/com/android/internal/security/VerityUtils.java +0 −215 Original line number Diff line number Diff line Loading @@ -18,28 +18,15 @@ package com.android.internal.security; import android.annotation.NonNull; import android.os.Build; import android.os.SharedMemory; import android.os.SystemProperties; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.util.Pair; import android.util.Slog; import android.util.apk.ApkSignatureVerifier; import android.util.apk.ByteBufferFactory; import android.util.apk.SignatureNotFoundException; import libcore.util.HexEncoding; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Paths; import java.security.DigestException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; /** Provides fsverity related operations. */ public abstract class VerityUtils { Loading @@ -57,8 +44,6 @@ public abstract class VerityUtils { /** SHA256 hash size. */ private static final int HASH_SIZE_BYTES = 32; private static final boolean DEBUG = false; public static boolean isFsVeritySupported() { return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R || SystemProperties.getInt("ro.apk_verity.mode", 0) == 2; Loading Loading @@ -123,204 +108,4 @@ public abstract class VerityUtils { private static native int measureFsverityNative(@NonNull String filePath, @NonNull byte[] digest); private static native int statxForFsverityNative(@NonNull String filePath); /** * Generates legacy Merkle tree and fs-verity metadata with Signing Block skipped. * * @deprecated This is only used for previous fs-verity implementation, and should never be used * on new devices. * @return {@code SetupResult} that contains the result code, and when success, the * {@code FileDescriptor} to read all the data from. */ @Deprecated public static SetupResult generateApkVeritySetupData(@NonNull String apkPath) { if (DEBUG) { Slog.d(TAG, "Trying to install legacy apk verity to " + apkPath); } SharedMemory shm = null; try { final byte[] signedVerityHash = ApkSignatureVerifier.getVerityRootHash(apkPath); if (signedVerityHash == null) { if (DEBUG) { Slog.d(TAG, "Skip verity tree generation since there is no signed root hash"); } return SetupResult.skipped(); } Pair<SharedMemory, Integer> result = generateFsVerityIntoSharedMemory(apkPath, signedVerityHash); shm = result.first; int contentSize = result.second; FileDescriptor rfd = shm.getFileDescriptor(); if (rfd == null || !rfd.valid()) { return SetupResult.failed(); } return SetupResult.ok(Os.dup(rfd), contentSize); } catch (IOException | SecurityException | DigestException | NoSuchAlgorithmException | SignatureNotFoundException | ErrnoException e) { Slog.e(TAG, "Failed to set up apk verity: ", e); return SetupResult.failed(); } finally { if (shm != null) { shm.close(); } } } /** * {@see ApkSignatureVerifier#generateApkVerityRootHash(String)}. * @deprecated This is only used for previous fs-verity implementation, and should never be used * on new devices. */ @Deprecated public static byte[] generateApkVerityRootHash(@NonNull String apkPath) throws NoSuchAlgorithmException, DigestException, IOException { return ApkSignatureVerifier.generateApkVerityRootHash(apkPath); } /** * {@see ApkSignatureVerifier#getVerityRootHash(String)}. * @deprecated This is only used for previous fs-verity implementation, and should never be used * on new devices. */ @Deprecated public static byte[] getVerityRootHash(@NonNull String apkPath) throws IOException, SignatureNotFoundException { return ApkSignatureVerifier.getVerityRootHash(apkPath); } /** * Returns a pair of {@code SharedMemory} and {@code Integer}. The {@code SharedMemory} contains * Merkle tree and fsverity headers for the given apk, in the form that can immediately be used * for fsverity setup. The data is aligned to the beginning of {@code SharedMemory}, and has * length equals to the returned {@code Integer}. */ private static Pair<SharedMemory, Integer> generateFsVerityIntoSharedMemory(String apkPath, @NonNull byte[] expectedRootHash) throws IOException, DigestException, NoSuchAlgorithmException, SignatureNotFoundException { TrackedShmBufferFactory shmBufferFactory = new TrackedShmBufferFactory(); byte[] generatedRootHash = ApkSignatureVerifier.generateApkVerity(apkPath, shmBufferFactory); // We only generate Merkle tree once here, so it's important to make sure the root hash // matches the signed one in the apk. if (!Arrays.equals(expectedRootHash, generatedRootHash)) { throw new SecurityException("verity hash mismatch: " + bytesToString(generatedRootHash) + " != " + bytesToString(expectedRootHash)); } int contentSize = shmBufferFactory.getBufferLimit(); SharedMemory shm = shmBufferFactory.releaseSharedMemory(); if (shm == null) { throw new IllegalStateException("Failed to generate verity tree into shared memory"); } if (!shm.setProtect(OsConstants.PROT_READ)) { throw new SecurityException("Failed to set up shared memory correctly"); } return Pair.create(shm, contentSize); } private static String bytesToString(byte[] bytes) { return HexEncoding.encodeToString(bytes); } /** * @deprecated This is only used for previous fs-verity implementation, and should never be used * on new devices. */ @Deprecated public static class SetupResult { /** Result code if verity is set up correctly. */ private static final int RESULT_OK = 1; /** Result code if signature is not provided. */ private static final int RESULT_SKIPPED = 2; /** Result code if the setup failed. */ private static final int RESULT_FAILED = 3; private final int mCode; private final FileDescriptor mFileDescriptor; private final int mContentSize; /** @deprecated */ @Deprecated public static SetupResult ok(@NonNull FileDescriptor fileDescriptor, int contentSize) { return new SetupResult(RESULT_OK, fileDescriptor, contentSize); } /** @deprecated */ @Deprecated public static SetupResult skipped() { return new SetupResult(RESULT_SKIPPED, null, -1); } /** @deprecated */ @Deprecated public static SetupResult failed() { return new SetupResult(RESULT_FAILED, null, -1); } private SetupResult(int code, FileDescriptor fileDescriptor, int contentSize) { this.mCode = code; this.mFileDescriptor = fileDescriptor; this.mContentSize = contentSize; } public boolean isFailed() { return mCode == RESULT_FAILED; } public boolean isOk() { return mCode == RESULT_OK; } public @NonNull FileDescriptor getUnownedFileDescriptor() { return mFileDescriptor; } public int getContentSize() { return mContentSize; } } /** A {@code ByteBufferFactory} that creates a shared memory backed {@code ByteBuffer}. */ private static class TrackedShmBufferFactory implements ByteBufferFactory { private SharedMemory mShm; private ByteBuffer mBuffer; @Override public ByteBuffer create(int capacity) { try { if (DEBUG) Slog.d(TAG, "Creating shared memory for apk verity"); // NB: This method is supposed to be called once according to the contract with // ApkSignatureSchemeV2Verifier. if (mBuffer != null) { throw new IllegalStateException("Multiple instantiation from this factory"); } mShm = SharedMemory.create("apkverity", capacity); if (!mShm.setProtect(OsConstants.PROT_READ | OsConstants.PROT_WRITE)) { throw new SecurityException("Failed to set protection"); } mBuffer = mShm.mapReadWrite(); return mBuffer; } catch (ErrnoException e) { throw new SecurityException("Failed to set protection", e); } } public SharedMemory releaseSharedMemory() { if (mBuffer != null) { SharedMemory.unmap(mBuffer); mBuffer = null; } SharedMemory tmp = mShm; mShm = null; return tmp; } public int getBufferLimit() { return mBuffer == null ? -1 : mBuffer.limit(); } } } Loading
core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java +0 −14 Original line number Diff line number Diff line Loading @@ -407,20 +407,6 @@ public class ApkSignatureSchemeV2Verifier { } } static byte[] generateApkVerityRootHash(String apkPath) throws IOException, SignatureNotFoundException, DigestException, NoSuchAlgorithmException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { SignatureInfo signatureInfo = findSignature(apk); VerifiedSigner vSigner = verify(apk, false); if (vSigner.verityRootHash == null) { return null; } return VerityBuilder.generateApkVerityRootHash( apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); } } /** * Verified APK Signature Scheme v2 signer. * Loading
core/java/android/util/apk/ApkSignatureSchemeV3Verifier.java +0 −14 Original line number Diff line number Diff line Loading @@ -444,20 +444,6 @@ public class ApkSignatureSchemeV3Verifier { } } static byte[] generateApkVerityRootHash(String apkPath) throws NoSuchAlgorithmException, DigestException, IOException, SignatureNotFoundException { try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) { SignatureInfo signatureInfo = findSignature(apk); VerifiedSigner vSigner = verify(apk, false); if (vSigner.verityRootHash == null) { return null; } return VerityBuilder.generateApkVerityRootHash( apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo); } } /** * Verified APK Signature Scheme v3 signer, including the proof of rotation structure. * Loading
core/java/android/util/apk/ApkSignatureVerifier.java +0 −21 Original line number Diff line number Diff line Loading @@ -550,27 +550,6 @@ public class ApkSignatureVerifier { return ApkSignatureSchemeV2Verifier.generateApkVerity(apkPath, bufferFactory); } /** * Generates the FSVerity root hash from FSVerity header, extensions and Merkle tree root hash * in Signing Block. * * @return FSverity root hash */ public static byte[] generateApkVerityRootHash(String apkPath) throws NoSuchAlgorithmException, DigestException, IOException { // first try v3 try { return ApkSignatureSchemeV3Verifier.generateApkVerityRootHash(apkPath); } catch (SignatureNotFoundException e) { // try older version } try { return ApkSignatureSchemeV2Verifier.generateApkVerityRootHash(apkPath); } catch (SignatureNotFoundException e) { return null; } } /** * Extended signing details. * @hide for internal use only. Loading
core/java/android/util/apk/VerityBuilder.java +0 −19 Original line number Diff line number Diff line Loading @@ -143,25 +143,6 @@ public abstract class VerityBuilder { return generateFsVerityTreeInternal(apk, salt, levelOffset, tree); } } /** * Calculates the apk-verity root hash for integrity measurement. This needs to be consistent * to what kernel returns. */ @NonNull static byte[] generateApkVerityRootHash(@NonNull RandomAccessFile apk, @NonNull ByteBuffer apkDigest, @NonNull SignatureInfo signatureInfo) throws NoSuchAlgorithmException, DigestException, IOException { assertSigningBlockAlignedAndHasFullPages(signatureInfo); ByteBuffer footer = ByteBuffer.allocate(CHUNK_SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN); generateApkVerityFooter(apk, signatureInfo, footer); footer.flip(); MessageDigest md = MessageDigest.getInstance(JCA_DIGEST_ALGORITHM); md.update(footer); md.update(apkDigest); return md.digest(); } /** * Generates the apk-verity header and hash tree to be used by kernel for the given apk. This Loading
core/java/com/android/internal/security/VerityUtils.java +0 −215 Original line number Diff line number Diff line Loading @@ -18,28 +18,15 @@ package com.android.internal.security; import android.annotation.NonNull; import android.os.Build; import android.os.SharedMemory; import android.os.SystemProperties; import android.system.ErrnoException; import android.system.Os; import android.system.OsConstants; import android.util.Pair; import android.util.Slog; import android.util.apk.ApkSignatureVerifier; import android.util.apk.ByteBufferFactory; import android.util.apk.SignatureNotFoundException; import libcore.util.HexEncoding; import java.io.File; import java.io.FileDescriptor; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.file.Files; import java.nio.file.Paths; import java.security.DigestException; import java.security.NoSuchAlgorithmException; import java.util.Arrays; /** Provides fsverity related operations. */ public abstract class VerityUtils { Loading @@ -57,8 +44,6 @@ public abstract class VerityUtils { /** SHA256 hash size. */ private static final int HASH_SIZE_BYTES = 32; private static final boolean DEBUG = false; public static boolean isFsVeritySupported() { return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R || SystemProperties.getInt("ro.apk_verity.mode", 0) == 2; Loading Loading @@ -123,204 +108,4 @@ public abstract class VerityUtils { private static native int measureFsverityNative(@NonNull String filePath, @NonNull byte[] digest); private static native int statxForFsverityNative(@NonNull String filePath); /** * Generates legacy Merkle tree and fs-verity metadata with Signing Block skipped. * * @deprecated This is only used for previous fs-verity implementation, and should never be used * on new devices. * @return {@code SetupResult} that contains the result code, and when success, the * {@code FileDescriptor} to read all the data from. */ @Deprecated public static SetupResult generateApkVeritySetupData(@NonNull String apkPath) { if (DEBUG) { Slog.d(TAG, "Trying to install legacy apk verity to " + apkPath); } SharedMemory shm = null; try { final byte[] signedVerityHash = ApkSignatureVerifier.getVerityRootHash(apkPath); if (signedVerityHash == null) { if (DEBUG) { Slog.d(TAG, "Skip verity tree generation since there is no signed root hash"); } return SetupResult.skipped(); } Pair<SharedMemory, Integer> result = generateFsVerityIntoSharedMemory(apkPath, signedVerityHash); shm = result.first; int contentSize = result.second; FileDescriptor rfd = shm.getFileDescriptor(); if (rfd == null || !rfd.valid()) { return SetupResult.failed(); } return SetupResult.ok(Os.dup(rfd), contentSize); } catch (IOException | SecurityException | DigestException | NoSuchAlgorithmException | SignatureNotFoundException | ErrnoException e) { Slog.e(TAG, "Failed to set up apk verity: ", e); return SetupResult.failed(); } finally { if (shm != null) { shm.close(); } } } /** * {@see ApkSignatureVerifier#generateApkVerityRootHash(String)}. * @deprecated This is only used for previous fs-verity implementation, and should never be used * on new devices. */ @Deprecated public static byte[] generateApkVerityRootHash(@NonNull String apkPath) throws NoSuchAlgorithmException, DigestException, IOException { return ApkSignatureVerifier.generateApkVerityRootHash(apkPath); } /** * {@see ApkSignatureVerifier#getVerityRootHash(String)}. * @deprecated This is only used for previous fs-verity implementation, and should never be used * on new devices. */ @Deprecated public static byte[] getVerityRootHash(@NonNull String apkPath) throws IOException, SignatureNotFoundException { return ApkSignatureVerifier.getVerityRootHash(apkPath); } /** * Returns a pair of {@code SharedMemory} and {@code Integer}. The {@code SharedMemory} contains * Merkle tree and fsverity headers for the given apk, in the form that can immediately be used * for fsverity setup. The data is aligned to the beginning of {@code SharedMemory}, and has * length equals to the returned {@code Integer}. */ private static Pair<SharedMemory, Integer> generateFsVerityIntoSharedMemory(String apkPath, @NonNull byte[] expectedRootHash) throws IOException, DigestException, NoSuchAlgorithmException, SignatureNotFoundException { TrackedShmBufferFactory shmBufferFactory = new TrackedShmBufferFactory(); byte[] generatedRootHash = ApkSignatureVerifier.generateApkVerity(apkPath, shmBufferFactory); // We only generate Merkle tree once here, so it's important to make sure the root hash // matches the signed one in the apk. if (!Arrays.equals(expectedRootHash, generatedRootHash)) { throw new SecurityException("verity hash mismatch: " + bytesToString(generatedRootHash) + " != " + bytesToString(expectedRootHash)); } int contentSize = shmBufferFactory.getBufferLimit(); SharedMemory shm = shmBufferFactory.releaseSharedMemory(); if (shm == null) { throw new IllegalStateException("Failed to generate verity tree into shared memory"); } if (!shm.setProtect(OsConstants.PROT_READ)) { throw new SecurityException("Failed to set up shared memory correctly"); } return Pair.create(shm, contentSize); } private static String bytesToString(byte[] bytes) { return HexEncoding.encodeToString(bytes); } /** * @deprecated This is only used for previous fs-verity implementation, and should never be used * on new devices. */ @Deprecated public static class SetupResult { /** Result code if verity is set up correctly. */ private static final int RESULT_OK = 1; /** Result code if signature is not provided. */ private static final int RESULT_SKIPPED = 2; /** Result code if the setup failed. */ private static final int RESULT_FAILED = 3; private final int mCode; private final FileDescriptor mFileDescriptor; private final int mContentSize; /** @deprecated */ @Deprecated public static SetupResult ok(@NonNull FileDescriptor fileDescriptor, int contentSize) { return new SetupResult(RESULT_OK, fileDescriptor, contentSize); } /** @deprecated */ @Deprecated public static SetupResult skipped() { return new SetupResult(RESULT_SKIPPED, null, -1); } /** @deprecated */ @Deprecated public static SetupResult failed() { return new SetupResult(RESULT_FAILED, null, -1); } private SetupResult(int code, FileDescriptor fileDescriptor, int contentSize) { this.mCode = code; this.mFileDescriptor = fileDescriptor; this.mContentSize = contentSize; } public boolean isFailed() { return mCode == RESULT_FAILED; } public boolean isOk() { return mCode == RESULT_OK; } public @NonNull FileDescriptor getUnownedFileDescriptor() { return mFileDescriptor; } public int getContentSize() { return mContentSize; } } /** A {@code ByteBufferFactory} that creates a shared memory backed {@code ByteBuffer}. */ private static class TrackedShmBufferFactory implements ByteBufferFactory { private SharedMemory mShm; private ByteBuffer mBuffer; @Override public ByteBuffer create(int capacity) { try { if (DEBUG) Slog.d(TAG, "Creating shared memory for apk verity"); // NB: This method is supposed to be called once according to the contract with // ApkSignatureSchemeV2Verifier. if (mBuffer != null) { throw new IllegalStateException("Multiple instantiation from this factory"); } mShm = SharedMemory.create("apkverity", capacity); if (!mShm.setProtect(OsConstants.PROT_READ | OsConstants.PROT_WRITE)) { throw new SecurityException("Failed to set protection"); } mBuffer = mShm.mapReadWrite(); return mBuffer; } catch (ErrnoException e) { throw new SecurityException("Failed to set protection", e); } } public SharedMemory releaseSharedMemory() { if (mBuffer != null) { SharedMemory.unmap(mBuffer); mBuffer = null; } SharedMemory tmp = mShm; mShm = null; return tmp; } public int getBufferLimit() { return mBuffer == null ? -1 : mBuffer.limit(); } } }