Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e1d0dfd9 authored by Automerger Merge Worker's avatar Automerger Merge Worker Committed by Android (Google) Code Review
Browse files

Merge "Merge "Close file streams" into rvc-dev am: 88d8768a am: 67ed6abd"...

Merge "Merge "Close file streams" into rvc-dev am: 88d8768a am: 67ed6abd" into rvc-d1-dev-plus-aosp
parents f78b440a f1fc7a5a
Loading
Loading
Loading
Loading
+37 −25
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.util.apk.ApkSigningBlockUtils.isSupportedSignatureAlgorith
import static android.util.apk.ApkSigningBlockUtils.readLengthPrefixedByteArray;

import android.util.Pair;
import android.util.Slog;
import android.util.jar.StrictJarFile;

import libcore.io.IoUtils;
@@ -69,6 +70,8 @@ import java.util.zip.ZipEntry;
 */
public abstract class SourceStampVerifier {

    private static final String TAG = "SourceStampVerifier";

    private static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a;
    private static final int APK_SIGNATURE_SCHEME_V3_BLOCK_ID = 0xf05368c0;
    private static final int SOURCE_STAMP_BLOCK_ID = 0x2b09189e;
@@ -99,28 +102,31 @@ public abstract class SourceStampVerifier {

    /** Verifies SourceStamp present in the provided APK. */
    public static SourceStampVerificationResult verify(String apkFile) {
        StrictJarFile apkJar = null;
        try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) {
            return verify(apk);
        } catch (IOException e) {
            // Any exception in reading the APK returns a non-present SourceStamp outcome
            // without affecting the outcome of any of the other signature schemes.
            return SourceStampVerificationResult.notPresent();
        }
    }

    private static SourceStampVerificationResult verify(RandomAccessFile apk) {
        byte[] sourceStampCertificateDigest;
        try {
            sourceStampCertificateDigest = getSourceStampCertificateDigest(apk);
            apkJar =
                    new StrictJarFile(
                            apkFile,
                            /* verify= */ false,
                            /* signatureSchemeRollbackProtectionsEnforced= */ false);
            byte[] sourceStampCertificateDigest = getSourceStampCertificateDigest(apkJar);
            if (sourceStampCertificateDigest == null) {
                // SourceStamp certificate hash file not found, which means that there is not
                // SourceStamp present.
                return SourceStampVerificationResult.notPresent();
            }
            return verify(apk, sourceStampCertificateDigest);
        } catch (IOException e) {
            // Any exception in reading the APK returns a non-present SourceStamp outcome
            // without affecting the outcome of any of the other signature schemes.
            return SourceStampVerificationResult.notPresent();
        } finally {
            closeApkJar(apkJar);
        }
    }

    private static SourceStampVerificationResult verify(
            RandomAccessFile apk, byte[] sourceStampCertificateDigest) {
        try {
            SignatureInfo signatureInfo =
                    ApkSigningBlockUtils.findSignature(apk, SOURCE_STAMP_BLOCK_ID);
@@ -283,22 +289,17 @@ public abstract class SourceStampVerifier {
        return apkContentDigests;
    }

    private static byte[] getSourceStampCertificateDigest(RandomAccessFile apk) throws IOException {
        StrictJarFile apkJar =
                new StrictJarFile(
                        apk.getFD(),
                        /* verify= */ false,
                        /* signatureSchemeRollbackProtectionsEnforced= */ false);
    private static byte[] getSourceStampCertificateDigest(StrictJarFile apkJar) throws IOException {
        InputStream inputStream = null;
        try {
            ZipEntry zipEntry = apkJar.findEntry(SOURCE_STAMP_CERTIFICATE_HASH_ZIP_ENTRY_NAME);
            if (zipEntry == null) {
                // SourceStamp certificate hash file not found, which means that there is not
                // SourceStamp present.
                return null;
            }
        InputStream inputStream = null;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            inputStream = apkJar.getInputStream(zipEntry);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

            // Trying to read the certificate digest, which should be less than 1024 bytes.
            byte[] buffer = new byte[1024];
@@ -327,4 +328,15 @@ public abstract class SourceStampVerifier {
        }
        return result.array();
    }

    private static void closeApkJar(StrictJarFile apkJar) {
        try {
            if (apkJar == null) {
                return;
            }
            apkJar.close();
        } catch (IOException e) {
            Slog.e(TAG, "Could not close APK jar", e);
        }
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
@@ -88,6 +89,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/** Implementation of {@link AppIntegrityManagerService}. */
public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
@@ -473,9 +475,9 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {

        SourceStampVerificationResult sourceStampVerificationResult;
        if (installationPath.isDirectory()) {
            try {
            try (Stream<Path> filesList = Files.list(installationPath.toPath())) {
                List<String> apkFiles =
                        Files.list(installationPath.toPath())
                        filesList
                                .map(path -> path.toAbsolutePath().toString())
                                .collect(Collectors.toList());
                sourceStampVerificationResult = SourceStampVerifier.verify(apkFiles);