Merge "dump apk signing version" into nyc-dev
am: 40a6e6a10e
* commit '40a6e6a10e0b411fd7434d586f2323674b11b757':
dump apk signing version
This commit is contained in:
@@ -121,6 +121,10 @@ public class PackageParser {
|
||||
|
||||
private static final int MAX_PACKAGES_PER_APK = 5;
|
||||
|
||||
public static final int APK_SIGNING_UNKNOWN = 0;
|
||||
public static final int APK_SIGNING_V1 = 1;
|
||||
public static final int APK_SIGNING_V2 = 2;
|
||||
|
||||
// TODO: switch outError users to PackageParserException
|
||||
// TODO: refactor "codePath" to "apkPath"
|
||||
|
||||
@@ -1058,12 +1062,24 @@ public class PackageParser {
|
||||
return pkg;
|
||||
}
|
||||
|
||||
public static int getApkSigningVersion(Package pkg) {
|
||||
try {
|
||||
if (ApkSignatureSchemeV2Verifier.hasSignature(pkg.baseCodePath)) {
|
||||
return APK_SIGNING_V2;
|
||||
}
|
||||
return APK_SIGNING_V1;
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return APK_SIGNING_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect certificates from all the APKs described in the given package,
|
||||
* populating {@link Package#mSignatures}. Also asserts that all APK
|
||||
* contents are signed correctly and consistently.
|
||||
*/
|
||||
public static void collectCertificates(Package pkg, int parseFlags) throws PackageParserException {
|
||||
public static void collectCertificates(Package pkg, int parseFlags)
|
||||
throws PackageParserException {
|
||||
collectCertificatesInternal(pkg, parseFlags);
|
||||
final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
@@ -1074,7 +1090,8 @@ public class PackageParser {
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectCertificatesInternal(Package pkg, int parseFlags) throws PackageParserException {
|
||||
private static void collectCertificatesInternal(Package pkg, int parseFlags)
|
||||
throws PackageParserException {
|
||||
pkg.mCertificates = null;
|
||||
pkg.mSignatures = null;
|
||||
pkg.mSigningKeys = null;
|
||||
|
||||
@@ -74,6 +74,36 @@ public class ApkSignatureSchemeV2Verifier {
|
||||
public static final String SF_ATTRIBUTE_ANDROID_APK_SIGNED_NAME = "X-Android-APK-Signed";
|
||||
public static final int SF_ATTRIBUTE_ANDROID_APK_SIGNED_ID = 2;
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the provided APK contains an APK Signature Scheme V2
|
||||
* signature. The signature will not be verified.
|
||||
*/
|
||||
public static boolean hasSignature(String apkFile) throws IOException {
|
||||
try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) {
|
||||
long fileSize = apk.length();
|
||||
if (fileSize > Integer.MAX_VALUE) {
|
||||
return false;
|
||||
}
|
||||
MappedByteBuffer apkContents =
|
||||
apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
|
||||
// ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
|
||||
apkContents.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
final int centralDirOffset =
|
||||
(int) getCentralDirOffset(apkContents, getEocdOffset(apkContents));
|
||||
// Find the APK Signing Block.
|
||||
int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
|
||||
ByteBuffer apkSigningBlock =
|
||||
sliceFromTo(apkContents, apkSigningBlockOffset, centralDirOffset);
|
||||
|
||||
// Find the APK Signature Scheme v2 Block inside the APK Signing Block.
|
||||
findApkSignatureSchemeV2Block(apkSigningBlock);
|
||||
return true;
|
||||
} catch (SignatureNotFoundException e) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies APK Signature Scheme v2 signatures of the provided APK and returns the certificates
|
||||
* associated with each signer.
|
||||
@@ -130,31 +160,8 @@ public class ApkSignatureSchemeV2Verifier {
|
||||
// ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
|
||||
apkContents.order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
// Find the offset of ZIP End of Central Directory (EoCD)
|
||||
int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
|
||||
if (eocdOffset == -1) {
|
||||
throw new SignatureNotFoundException(
|
||||
"Not an APK file: ZIP End of Central Directory record not found");
|
||||
}
|
||||
if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
|
||||
throw new SignatureNotFoundException("ZIP64 APK not supported");
|
||||
}
|
||||
ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
|
||||
|
||||
// Look up the offset of ZIP Central Directory.
|
||||
long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
|
||||
if (centralDirOffsetLong >= eocdOffset) {
|
||||
throw new SignatureNotFoundException(
|
||||
"ZIP Central Directory offset out of range: " + centralDirOffsetLong
|
||||
+ ". ZIP End of Central Directory offset: " + eocdOffset);
|
||||
}
|
||||
long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
|
||||
if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
|
||||
throw new SignatureNotFoundException(
|
||||
"ZIP Central Directory is not immediately followed by End of Central"
|
||||
+ " Directory");
|
||||
}
|
||||
int centralDirOffset = (int) centralDirOffsetLong;
|
||||
final int eocdOffset = getEocdOffset(apkContents);
|
||||
final int centralDirOffset = (int) getCentralDirOffset(apkContents, eocdOffset);
|
||||
|
||||
// Find the APK Signing Block.
|
||||
int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
|
||||
@@ -499,6 +506,43 @@ public class ApkSignatureSchemeV2Verifier {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the offset of ZIP End of Central Directory (EoCD).
|
||||
*
|
||||
* @throws SignatureNotFoundException If the EoCD could not be found
|
||||
*/
|
||||
private static int getEocdOffset(ByteBuffer apkContents) throws SignatureNotFoundException {
|
||||
int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
|
||||
if (eocdOffset == -1) {
|
||||
throw new SignatureNotFoundException(
|
||||
"Not an APK file: ZIP End of Central Directory record not found");
|
||||
}
|
||||
return eocdOffset;
|
||||
}
|
||||
|
||||
private static long getCentralDirOffset(ByteBuffer apkContents, int eocdOffset)
|
||||
throws SignatureNotFoundException {
|
||||
if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
|
||||
throw new SignatureNotFoundException("ZIP64 APK not supported");
|
||||
}
|
||||
ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
|
||||
|
||||
// Look up the offset of ZIP Central Directory.
|
||||
long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
|
||||
if (centralDirOffsetLong >= eocdOffset) {
|
||||
throw new SignatureNotFoundException(
|
||||
"ZIP Central Directory offset out of range: " + centralDirOffsetLong
|
||||
+ ". ZIP End of Central Directory offset: " + eocdOffset);
|
||||
}
|
||||
long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
|
||||
if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
|
||||
throw new SignatureNotFoundException(
|
||||
"ZIP Central Directory is not immediately followed by End of Central"
|
||||
+ " Directory");
|
||||
}
|
||||
return centralDirOffsetLong;
|
||||
}
|
||||
|
||||
private static final int getChunkCount(int inputSizeBytes) {
|
||||
return (inputSizeBytes + CHUNK_SIZE_BYTES - 1) / CHUNK_SIZE_BYTES;
|
||||
}
|
||||
|
||||
@@ -2604,7 +2604,6 @@ final class Settings {
|
||||
if (pkg.volumeUuid != null) {
|
||||
serializer.attribute(null, "volumeUuid", pkg.volumeUuid);
|
||||
}
|
||||
|
||||
if (pkg.parentPackageName != null) {
|
||||
serializer.attribute(null, "parentPackageName", pkg.parentPackageName);
|
||||
}
|
||||
@@ -4316,6 +4315,10 @@ final class Settings {
|
||||
}
|
||||
pw.print(prefix); pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
|
||||
pw.print(prefix); pw.print(" splits="); dumpSplitNames(pw, ps.pkg); pw.println();
|
||||
final int apkSigningVersion = PackageParser.getApkSigningVersion(ps.pkg);
|
||||
if (apkSigningVersion != PackageParser.APK_SIGNING_UNKNOWN) {
|
||||
pw.print(prefix); pw.print(" apkSigningVersion="); pw.println(apkSigningVersion);
|
||||
}
|
||||
pw.print(prefix); pw.print(" applicationInfo=");
|
||||
pw.println(ps.pkg.applicationInfo.toString());
|
||||
pw.print(prefix); pw.print(" flags="); printFlags(pw, ps.pkg.applicationInfo.flags,
|
||||
|
||||
Reference in New Issue
Block a user