aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-27 02:29:53 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-27 02:29:53 +0000
commitda15f1a63dd5f0c1fcf028d74f4ddaba958649d1 (patch)
tree1ae1b08ee2d1c16d9e5dd9c19cf4b7c71f0ece3e
parentd2a87a63d14286b455f4718874678e21819a434f (diff)
parentc2a8da1913d7fb359b023bf200e31d75ff22a5c3 (diff)
downloadapksig-da15f1a63dd5f0c1fcf028d74f4ddaba958649d1.tar.gz
Snap for 8771415 from c2a8da1913d7fb359b023bf200e31d75ff22a5c3 to gki13-boot-release
Change-Id: Ic926c15795029e7ea6f7915570d4f3a3064b9b78
-rw-r--r--src/apksigner/java/com/android/apksigner/ApkSignerTool.java4
-rw-r--r--src/apksigner/java/com/android/apksigner/help_sign.txt2
-rw-r--r--src/main/java/com/android/apksig/ApkSigner.java55
-rw-r--r--src/main/java/com/android/apksig/internal/zip/EocdRecord.java9
-rw-r--r--src/test/java/com/android/apksig/ApkSignerTest.java19
-rw-r--r--src/test/resources/com/android/apksig/golden-file-size-aligned.apkbin0 -> 16384 bytes
6 files changed, 86 insertions, 3 deletions
diff --git a/src/apksigner/java/com/android/apksigner/ApkSignerTool.java b/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
index 9fd0c34..d21515c 100644
--- a/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
+++ b/src/apksigner/java/com/android/apksigner/ApkSignerTool.java
@@ -142,6 +142,7 @@ public class ApkSignerTool {
boolean v3SigningEnabled = true;
boolean v4SigningEnabled = true;
boolean forceSourceStampOverwrite = false;
+ boolean alignFileSize = false;
boolean verityEnabled = false;
boolean debuggableApkPermitted = true;
int minSdkVersion = 1;
@@ -186,6 +187,8 @@ public class ApkSignerTool {
v4SigningFlagFound = true;
} else if ("force-stamp-overwrite".equals(optionName)) {
forceSourceStampOverwrite = optionsParser.getOptionalBooleanValue(true);
+ } else if ("align-file-size".equals(optionName)) {
+ alignFileSize = true;
} else if ("verity-enabled".equals(optionName)) {
verityEnabled = optionsParser.getOptionalBooleanValue(true);
} else if ("debuggable-apk-permitted".equals(optionName)) {
@@ -359,6 +362,7 @@ public class ApkSignerTool {
.setV3SigningEnabled(v3SigningEnabled)
.setV4SigningEnabled(v4SigningEnabled)
.setForceSourceStampOverwrite(forceSourceStampOverwrite)
+ .setAlignFileSize(alignFileSize)
.setVerityEnabled(verityEnabled)
.setV4ErrorReportingEnabled(v4SigningEnabled && v4SigningFlagFound)
.setDebuggableApkPermitted(debuggableApkPermitted)
diff --git a/src/apksigner/java/com/android/apksigner/help_sign.txt b/src/apksigner/java/com/android/apksigner/help_sign.txt
index d66b7a3..5266ad9 100644
--- a/src/apksigner/java/com/android/apksigner/help_sign.txt
+++ b/src/apksigner/java/com/android/apksigner/help_sign.txt
@@ -50,6 +50,8 @@ certificate.
APK, if found. By default, it is set to false. It has no
effect if no source stamp signer config is provided.
+--align-file-size Produces APK file sized as multiples of 4K bytes.
+
--verity-enabled Whether to enable the verity signature algorithm for the
v2 and v3 signature schemes.
diff --git a/src/main/java/com/android/apksig/ApkSigner.java b/src/main/java/com/android/apksig/ApkSigner.java
index ca792c4..d6c7799 100644
--- a/src/main/java/com/android/apksig/ApkSigner.java
+++ b/src/main/java/com/android/apksig/ApkSigner.java
@@ -81,6 +81,8 @@ public class ApkSigner {
private static final short ANDROID_COMMON_PAGE_ALIGNMENT_BYTES = 4096;
+ private static final short ANDROID_FILE_ALIGNMENT_BYTES = 4096;
+
/** Name of the Android manifest ZIP entry in APKs. */
private static final String ANDROID_MANIFEST_ZIP_ENTRY_NAME = "AndroidManifest.xml";
@@ -93,6 +95,7 @@ public class ApkSigner {
private final boolean mV2SigningEnabled;
private final boolean mV3SigningEnabled;
private final boolean mV4SigningEnabled;
+ private final boolean mAlignFileSize;
private final boolean mVerityEnabled;
private final boolean mV4ErrorReportingEnabled;
private final boolean mDebuggableApkPermitted;
@@ -122,6 +125,7 @@ public class ApkSigner {
boolean v2SigningEnabled,
boolean v3SigningEnabled,
boolean v4SigningEnabled,
+ boolean alignFileSize,
boolean verityEnabled,
boolean v4ErrorReportingEnabled,
boolean debuggableApkPermitted,
@@ -145,6 +149,7 @@ public class ApkSigner {
mV2SigningEnabled = v2SigningEnabled;
mV3SigningEnabled = v3SigningEnabled;
mV4SigningEnabled = v4SigningEnabled;
+ mAlignFileSize = alignFileSize;
mVerityEnabled = verityEnabled;
mV4ErrorReportingEnabled = v4ErrorReportingEnabled;
mDebuggableApkPermitted = debuggableApkPermitted;
@@ -579,6 +584,9 @@ public class ApkSigner {
int outputCentralDirRecordCount = outputCdRecords.size();
// Step 10. Construct output ZIP End of Central Directory record in an in-memory buffer
+ // because it can be adjusted in Step 11 due to signing block.
+ // - CD offset (it's shifted by signing block)
+ // - Comments (when the output file needs to be sized 4k-aligned)
ByteBuffer outputEocd =
EocdRecord.createWithModifiedCentralDirectoryInfo(
inputZipSections.getZipEndOfCentralDirectory(),
@@ -597,13 +605,39 @@ public class ApkSigner {
if (outputApkSigningBlockRequest != null) {
int padding = outputApkSigningBlockRequest.getPaddingSizeBeforeApkSigningBlock();
- outputApkOut.consume(ByteBuffer.allocate(padding));
byte[] outputApkSigningBlock = outputApkSigningBlockRequest.getApkSigningBlock();
+ outputApkSigningBlockRequest.done();
+
+ long fileSize =
+ outputCentralDirStartOffset
+ + outputCentralDirDataSource.size()
+ + padding
+ + outputApkSigningBlock.length
+ + outputEocd.remaining();
+ if (mAlignFileSize && (fileSize % ANDROID_FILE_ALIGNMENT_BYTES != 0)) {
+ int eocdPadding =
+ (int)
+ (ANDROID_FILE_ALIGNMENT_BYTES
+ - fileSize % ANDROID_FILE_ALIGNMENT_BYTES);
+ // Replace EOCD with padding one so that output file size can be the multiples of
+ // alignment.
+ outputEocd = EocdRecord.createWithPaddedComment(outputEocd, eocdPadding);
+
+ // Since EoCD has changed, we need to regenerate signing block as well.
+ outputApkSigningBlockRequest =
+ signerEngine.outputZipSections2(
+ outputApkIn,
+ new ByteBufferDataSource(outputCentralDir),
+ DataSources.asDataSource(outputEocd));
+ outputApkSigningBlock = outputApkSigningBlockRequest.getApkSigningBlock();
+ outputApkSigningBlockRequest.done();
+ }
+
+ outputApkOut.consume(ByteBuffer.allocate(padding));
outputApkOut.consume(outputApkSigningBlock, 0, outputApkSigningBlock.length);
ZipUtils.setZipEocdCentralDirectoryOffset(
outputEocd,
outputCentralDirStartOffset + padding + outputApkSigningBlock.length);
- outputApkSigningBlockRequest.done();
}
// Step 12. Output ZIP Central Directory and ZIP End of Central Directory
@@ -1087,6 +1121,7 @@ public class ApkSigner {
private boolean mV2SigningEnabled = true;
private boolean mV3SigningEnabled = true;
private boolean mV4SigningEnabled = true;
+ private boolean mAlignFileSize = false;
private boolean mVerityEnabled = false;
private boolean mV4ErrorReportingEnabled = false;
private boolean mDebuggableApkPermitted = true;
@@ -1411,6 +1446,21 @@ public class ApkSigner {
return this;
}
+ /**
+ * Sets whether the output APK files should be sized as multiples of 4K.
+ *
+ * <p><em>Note:</em> This method may only be invoked when this builder is not initialized
+ * with an {@link ApkSignerEngine}.
+ *
+ * @throws IllegalStateException if this builder was initialized with an {@link
+ * ApkSignerEngine}
+ */
+ public Builder setAlignFileSize(boolean alignFileSize) {
+ checkInitializedWithoutEngine();
+ mAlignFileSize = alignFileSize;
+ return this;
+ }
+
/**
* Sets whether to enable the verity signature algorithm for the v2 and v3 signature
* schemes.
@@ -1542,6 +1592,7 @@ public class ApkSigner {
mV2SigningEnabled,
mV3SigningEnabled,
mV4SigningEnabled,
+ mAlignFileSize,
mVerityEnabled,
mV4ErrorReportingEnabled,
mDebuggableApkPermitted,
diff --git a/src/main/java/com/android/apksig/internal/zip/EocdRecord.java b/src/main/java/com/android/apksig/internal/zip/EocdRecord.java
index 9c531f4..d2000b4 100644
--- a/src/main/java/com/android/apksig/internal/zip/EocdRecord.java
+++ b/src/main/java/com/android/apksig/internal/zip/EocdRecord.java
@@ -45,4 +45,13 @@ public class EocdRecord {
ZipUtils.setUnsignedInt32(result, CD_OFFSET_OFFSET, centralDirectoryOffset);
return result;
}
+
+ public static ByteBuffer createWithPaddedComment(ByteBuffer original, int padding) {
+ ByteBuffer result = ByteBuffer.allocate((int) original.remaining() + padding);
+ result.order(ByteOrder.LITTLE_ENDIAN);
+ result.put(original.slice());
+ result.rewind();
+ ZipUtils.updateZipEocdCommentLen(result);
+ return result;
+ }
}
diff --git a/src/test/java/com/android/apksig/ApkSignerTest.java b/src/test/java/com/android/apksig/ApkSignerTest.java
index d799201..69b8d4e 100644
--- a/src/test/java/com/android/apksig/ApkSignerTest.java
+++ b/src/test/java/com/android/apksig/ApkSignerTest.java
@@ -382,7 +382,11 @@ public class ApkSignerTest {
.setV2SigningEnabled(true)
.setV3SigningEnabled(true)
.setVerityEnabled(true));
-
+ signGolden(
+ "original.apk",
+ new File(outDir, "golden-file-size-aligned.apk"),
+ new ApkSigner.Builder(rsa2048SignerConfig)
+ .setAlignFileSize(true));
signGolden(
"pinsapp-unsigned.apk",
new File(outDir, "golden-pinsapp-signed.apk"),
@@ -695,6 +699,19 @@ public class ApkSignerTest {
}
@Test
+ public void testAlignFileSize_Golden() throws Exception {
+ List<ApkSigner.SignerConfig> rsaSignerConfig =
+ Collections.singletonList(
+ getDefaultSignerConfigFromResources(FIRST_RSA_2048_SIGNER_RESOURCE_NAME));
+ String goldenOutput = "golden-file-size-aligned.apk";
+ assertGolden(
+ "original.apk",
+ goldenOutput,
+ new ApkSigner.Builder(rsaSignerConfig).setAlignFileSize(true));
+ assertTrue(Resources.toByteArray(getClass(), goldenOutput).length % 4096 == 0);
+ }
+
+ @Test
public void testRsaSignedVerifies() throws Exception {
List<ApkSigner.SignerConfig> signers =
Collections.singletonList(
diff --git a/src/test/resources/com/android/apksig/golden-file-size-aligned.apk b/src/test/resources/com/android/apksig/golden-file-size-aligned.apk
new file mode 100644
index 0000000..8dd95fc
--- /dev/null
+++ b/src/test/resources/com/android/apksig/golden-file-size-aligned.apk
Binary files differ