Skip to content

Commit

Permalink
Support writing chanel to apk that signed by android signature scheme v3
Browse files Browse the repository at this point in the history
New scheme requires an extra dummy ID-value block padding to make size a multiple of 4096 bytes

See https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/apk/ApkVerityBuilder.java#445

Fixed Meituan-Dianping#256 Meituan-Dianping#255
  • Loading branch information
yrom committed Oct 23, 2018
1 parent b950fae commit 056359d
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ private ApkUtil() {
*/
public static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a;

/**
* The padding in APK SIG BLOCK (V3 scheme introduced)
* See https://android.googlesource.com/platform/tools/apksig/+/master/src/main/java/com/android/apksig/internal/apk/ApkSigningBlockUtils.java
*/
public static final int VERITY_PADDING_BLOCK_ID = 0x42726577;

public static final int ANDROID_COMMON_PAGE_ALIGNMENT_BYTES = 4096;


// Our Channel Block ID
public static final int APK_CHANNEL_BLOCK_ID = 0x71777777;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
class ApkSigningPayload {
private final int id;
private final ByteBuffer buffer;
private final int totalSize;

ApkSigningPayload(final int id, final ByteBuffer buffer) {
super();
Expand All @@ -15,6 +16,8 @@ class ApkSigningPayload {
throw new IllegalArgumentException("ByteBuffer byte order must be little endian");
}
this.buffer = buffer;
// assume buffer is not consumed
this.totalSize = 8 + 4 + buffer.remaining(); // size + id + value
}

public int getId() {
Expand All @@ -27,4 +30,11 @@ public byte[] getByteBuffer() {
return Arrays.copyOfRange(array, arrayOffset + buffer.position(),
arrayOffset + buffer.limit());
}

/**
* Total bytes of this block
*/
public int getTotalSize() {
return totalSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,35 @@ static void handleApkSigningBlock(final File apkFile, final ApkSigningBlockHandl
"No APK Signature Scheme v2 block in APK Signing Block");
}


final boolean needPadding = originIdValues.remove(ApkUtil.VERITY_PADDING_BLOCK_ID) != null;
final ApkSigningBlock apkSigningBlock = handler.handle(originIdValues);
// replace VERITY_PADDING_BLOCK with new one
if (needPadding) {
// uint64: size (excluding this field)
// repeated ID-value pairs:
// uint64: size (excluding this field)
// uint32: ID
// (size - 4) bytes: value
// (extra dummy ID-value for padding to make block size a multiple of 4096 bytes)
// uint64: size (same as the one above)
// uint128: magic

int blocksSize = 0;
for (ApkSigningPayload payload : apkSigningBlock.getPayloads()) {
blocksSize += payload.getTotalSize();
}

int resultSize = 8 + blocksSize + 8 + 16; // size(uint64) + pairs size + size(uint64) + magic(uint128)
if (resultSize % ApkUtil.ANDROID_COMMON_PAGE_ALIGNMENT_BYTES != 0) {
int padding = ApkUtil.ANDROID_COMMON_PAGE_ALIGNMENT_BYTES - 12 // size(uint64) + id(uint32)
- (resultSize % ApkUtil.ANDROID_COMMON_PAGE_ALIGNMENT_BYTES);
if (padding < 0) {
padding += ApkUtil.ANDROID_COMMON_PAGE_ALIGNMENT_BYTES;
}
final ByteBuffer dummy = ByteBuffer.allocate(padding).order(ByteOrder.LITTLE_ENDIAN);
apkSigningBlock.addPayload(new ApkSigningPayload(ApkUtil.VERITY_PADDING_BLOCK_ID,dummy));
}
}

if (apkSigningBlockOffset != 0 && centralDirStartOffset != 0) {

Expand Down

0 comments on commit 056359d

Please sign in to comment.