Merge "Calculate correct checksum." into tm-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
83962ee99c
@@ -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;
|
||||||
|
|||||||
@@ -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");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user