Skip to content

Commit

Permalink
Fix: support writing chanel to the apk signed by android signature sc…
Browse files Browse the repository at this point in the history
…heme v3

New scheme requires a extract 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 b4ee944
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(uint16) + blocks size + size(uint16) + magic
if (resultSize % ApkUtil.ANDROID_COMMON_PAGE_ALIGNMENT_BYTES != 0) {
int padding = ApkUtil.ANDROID_COMMON_PAGE_ALIGNMENT_BYTES -
(resultSize % ApkUtil.ANDROID_COMMON_PAGE_ALIGNMENT_BYTES);
if (padding < 12) { // minimum size of an ID-value pair
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 b4ee944

Please sign in to comment.