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

Commit 7f1d0ab2 authored by Alex Buynytskyy's avatar Alex Buynytskyy Committed by Automerger Merge Worker
Browse files

Merge "Calculate correct checksum." into tm-dev am: 83962ee9

parents 1db3c98f 83962ee9
Loading
Loading
Loading
Loading
+45 −8
Original line number Original line Diff line number Diff line
@@ -77,6 +77,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Files;
import java.security.DigestException;
import java.security.DigestException;
import java.security.InvalidParameterException;
import java.security.InvalidParameterException;
@@ -584,7 +585,7 @@ public class ApkChecksums {
                        });
                        });
                checksums.put(TYPE_WHOLE_MERKLE_ROOT_4K_SHA256,
                checksums.put(TYPE_WHOLE_MERKLE_ROOT_4K_SHA256,
                        new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256,
                        new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256,
                                generatedRootHash));
                                verityHashForFile(file, generatedRootHash)));
            } catch (IOException | NoSuchAlgorithmException | DigestException e) {
            } catch (IOException | NoSuchAlgorithmException | DigestException e) {
                Slog.e(TAG, "Error calculating WHOLE_MERKLE_ROOT_4K_SHA256", e);
                Slog.e(TAG, "Error calculating WHOLE_MERKLE_ROOT_4K_SHA256", e);
            }
            }
@@ -649,19 +650,20 @@ public class ApkChecksums {
        // Skip /product folder.
        // Skip /product folder.
        // TODO(b/231354111): remove this hack once we are allowed to change SELinux rules.
        // TODO(b/231354111): remove this hack once we are allowed to change SELinux rules.
        if (!containsFile(Environment.getProductDirectory(), filePath)) {
        if (!containsFile(Environment.getProductDirectory(), filePath)) {
            byte[] hash = VerityUtils.getFsverityRootHash(filePath);
            byte[] verityHash = VerityUtils.getFsverityRootHash(filePath);
            if (hash != null) {
            if (verityHash != null) {
                return new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, hash);
                return new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, verityHash);
            }
            }
        }
        }
        // v4 next
        // v4 next
        try {
        try {
            ApkSignatureSchemeV4Verifier.VerifiedSigner signer =
            ApkSignatureSchemeV4Verifier.VerifiedSigner signer =
                    ApkSignatureSchemeV4Verifier.extractCertificates(filePath);
                    ApkSignatureSchemeV4Verifier.extractCertificates(filePath);
            byte[] hash = signer.contentDigests.getOrDefault(CONTENT_DIGEST_VERITY_CHUNKED_SHA256,
            byte[] rootHash = signer.contentDigests.getOrDefault(
                    null);
                    CONTENT_DIGEST_VERITY_CHUNKED_SHA256, null);
            if (hash != null) {
            if (rootHash != null) {
                return new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256, hash);
                return new ApkChecksum(split, TYPE_WHOLE_MERKLE_ROOT_4K_SHA256,
                        verityHashForFile(new File(filePath), rootHash));
            }
            }
        } catch (SignatureNotFoundException e) {
        } catch (SignatureNotFoundException e) {
            // Nothing
            // Nothing
@@ -671,6 +673,41 @@ public class ApkChecksums {
        return null;
        return null;
    }
    }


    /**
     * Returns fs-verity digest as described in
     * https://www.kernel.org/doc/html/latest/filesystems/fsverity.html#fs-verity-descriptor
     * @param file the Merkle tree is built over
     * @param rootHash Merkle tree root hash
     */
    static byte[] verityHashForFile(File file, byte[] rootHash) {
        try {
            ByteBuffer buffer = ByteBuffer.allocate(256); // sizeof(fsverity_descriptor)
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            buffer.put((byte) 1);               // __u8 version, must be 1
            buffer.put((byte) 1);               // __u8 hash_algorithm, FS_VERITY_HASH_ALG_SHA256
            buffer.put((byte) 12);              // __u8, FS_VERITY_LOG_BLOCKSIZE
            buffer.put((byte) 0);               // __u8, size of salt in bytes; 0 if none
            buffer.putInt(0);                   // __le32 __reserved_0x04, must be 0
            buffer.putLong(file.length());      // __le64 data_size
            buffer.put(rootHash);               // root_hash, first 32 bytes
            final int padding = 32 + 32 + 144;  // root_hash, last 32 bytes, we are using sha256.
            // salt, 32 bytes
            // reserved, 144 bytes
            for (int i = 0; i < padding; ++i) {
                buffer.put((byte) 0);
            }

            buffer.flip();

            final MessageDigest md = MessageDigest.getInstance(ALGO_SHA256);
            md.update(buffer);
            return md.digest();
        } catch (NoSuchAlgorithmException e) {
            Slog.e(TAG, "Device does not support MessageDigest algorithm", e);
            return null;
        }
    }

    private static Map<Integer, ApkChecksum> extractHashFromV2V3Signature(
    private static Map<Integer, ApkChecksum> extractHashFromV2V3Signature(
            String split, String filePath, int types) {
            String split, String filePath, int types) {
        Map<Integer, byte[]> contentDigests = null;
        Map<Integer, byte[]> contentDigests = null;
+1 −1
Original line number Original line Diff line number Diff line
@@ -1069,7 +1069,7 @@ public class PackageManagerServiceUtils {
            if (ArrayUtils.isEmpty(hashInfo.rawRootHash)) {
            if (ArrayUtils.isEmpty(hashInfo.rawRootHash)) {
                throw new IOException("Root has not present");
                throw new IOException("Root has not present");
            }
            }
            return hashInfo.rawRootHash;
            return ApkChecksums.verityHashForFile(new File(filename), hashInfo.rawRootHash);
        } catch (IOException ignore) {
        } catch (IOException ignore) {
            Slog.e(TAG, "ERROR: could not load root hash from incremental install");
            Slog.e(TAG, "ERROR: could not load root hash from incremental install");
        }
        }