From 4ea28e7683f6d59dee6cde4ba87d0adf11101c25 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Fri, 21 Jun 2024 16:51:57 +0800 Subject: [PATCH 01/26] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20PageInfoExtension?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zfeixiang --- .../datastructure/PageInfoExtension.java | 51 +++++++++++++++++++ .../codesigning/datastructure/SignInfo.java | 6 +-- .../codesigning/sign/CodeSigning.java | 2 + 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java new file mode 100644 index 00000000..e44c18d4 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -0,0 +1,51 @@ +package com.ohos.hapsigntool.codesigning.datastructure; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class PageInfoExtension extends Extension { + /** + * Type of PageInfoExtension + */ + public static final int PAGE_INFO_INLINED = 0x2; + + /** + * Byte size of PageInfoExtension including merkleTreeSize, offset and root hash. + */ + public static final int PAGE_INFO_EXTENSION_DATA_SIZE = Extension.EXTENSION_HEADER_SIZE + 24; + + /** + * reserved size + */ + public static final int RESERVED_SIZE = 7; + + private long mapOffset; + + private long mapSize; + + private byte unitSize = 4; + + private byte[] reserved = new byte[RESERVED_SIZE]; + + public PageInfoExtension(long mapOffset, long mapSize) { + super(PAGE_INFO_INLINED, PAGE_INFO_EXTENSION_DATA_SIZE); + this.mapOffset = mapOffset; + this.mapSize = mapSize; + } + + @Override + public int size() { + return PAGE_INFO_EXTENSION_DATA_SIZE; + } + + @Override + public byte[] toByteArray() { + ByteBuffer bf = ByteBuffer.allocate(PAGE_INFO_EXTENSION_DATA_SIZE).order(ByteOrder.LITTLE_ENDIAN); + bf.put(super.toByteArray()); + bf.putLong(this.mapOffset); + bf.putLong(this.mapSize); + bf.put(this.unitSize); + bf.put(this.reserved); + return bf.array(); + } +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java index e2d538c4..ba16f463 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java @@ -58,7 +58,7 @@ public class SignInfo { /** * maximum of extension number */ - public static final int MAX_EXTENSION_NUM = 1; + public static final int MAX_EXTENSION_NUM = 2; /** * sign info structure without signature in bytes, refer to toByteArray() method @@ -138,7 +138,7 @@ public class SignInfo { * @param extension Extension object */ public void addExtension(Extension extension) { - this.extensionOffset = this.size(); + this.extensionOffset = SIGN_INFO_SIZE_WITHOUT_SIGNATURE + this.signature.length + this.zeroPadding.length; this.extensionList.add(extension); this.extensionNum = this.extensionList.size(); } @@ -271,7 +271,7 @@ public class SignInfo { private static List parseMerkleTreeExtension(ByteBuffer bf, int inExtensionNum) throws VerifyCodeSignException { List inExtensionList = new ArrayList<>(); - if (inExtensionNum == 1) { + if (inExtensionNum >= 1) { // parse merkle tree extension int extensionType = bf.getInt(); if (extensionType != MerkleTreeExtension.MERKLE_TREE_INLINED) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index 7993a7fc..20f238ed 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -20,6 +20,7 @@ import com.ohos.hapsigntool.codesigning.datastructure.ElfSignBlock; import com.ohos.hapsigntool.codesigning.datastructure.Extension; import com.ohos.hapsigntool.codesigning.datastructure.FsVerityInfoSegment; import com.ohos.hapsigntool.codesigning.datastructure.MerkleTreeExtension; +import com.ohos.hapsigntool.codesigning.datastructure.PageInfoExtension; import com.ohos.hapsigntool.codesigning.datastructure.SignInfo; import com.ohos.hapsigntool.codesigning.exception.CodeSignException; import com.ohos.hapsigntool.codesigning.exception.FsVerityDigestException; @@ -186,6 +187,7 @@ public class CodeSigning { fsvTreeOffset, ownerID); // update hap segment in CodeSignBlock this.codeSignBlock.getHapInfoSegment().setSignInfo(hapSignInfoAndMerkleTreeBytesPair.getFirst()); + this.codeSignBlock.getHapInfoSegment().getSignInfo().addExtension(new PageInfoExtension(0L, 0L)); // Insert merkle tree bytes into code sign block this.codeSignBlock.addOneMerkleTree(HAP_SIGNATURE_ENTRY_NAME, hapSignInfoAndMerkleTreeBytesPair.getSecond()); -- Gitee From 9cfdcdeeb07bf743371d3c3c6fc37017a02d91b1 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 29 Jun 2024 11:53:35 +0800 Subject: [PATCH 02/26] bitmap generator Signed-off-by: zfeixiang --- .../datastructure/HapInfoSegment.java | 2 +- .../datastructure/PageInfoExtension.java | 20 ++ .../codesigning/elf/ElfDefine.java | 36 ++++ .../hapsigntool/codesigning/elf/ElfFile.java | 47 +++++ .../codesigning/elf/ElfHeader.java | 142 +++++++++++++ .../codesigning/elf/ElfPHeader.java | 100 +++++++++ .../exception/ElfFormatException.java | 26 +++ .../codesigning/sign/CodeSigning.java | 22 +- .../codesigning/sign/PageInfoGenerator.java | 194 ++++++++++++++++++ 9 files changed, 587 insertions(+), 2 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/HapInfoSegment.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/HapInfoSegment.java index 2697ea7a..4b8be585 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/HapInfoSegment.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/HapInfoSegment.java @@ -121,7 +121,7 @@ public class HapInfoSegment { String.format(Locale.ROOT, "Invalid dataSize number of HapInfoSegment, not a multiple of 4096: %d", inHapSignInfo.getDataSize())); } - if (inHapSignInfo.getExtensionNum() != SignInfo.MAX_EXTENSION_NUM) { + if (inHapSignInfo.getExtensionNum() > SignInfo.MAX_EXTENSION_NUM) { throw new VerifyCodeSignException("Invalid extensionNum of HapInfoSegment"); } if (inHapSignInfo.getExtensionByType(MerkleTreeExtension.MERKLE_TREE_INLINED) == null) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java index e44c18d4..131c9a55 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.ohos.hapsigntool.codesigning.datastructure; import java.nio.ByteBuffer; @@ -14,6 +29,11 @@ public class PageInfoExtension extends Extension { */ public static final int PAGE_INFO_EXTENSION_DATA_SIZE = Extension.EXTENSION_HEADER_SIZE + 24; + /** + * default unit size + */ + public static final int DEFAULT_UNIT_SIZE = 4; + /** * reserved size */ diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java new file mode 100644 index 00000000..1702edaa --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.codesigning.elf; + +public interface ElfDefine { + byte Elf32Class = 1; + byte Elf64Class = 2; + byte ElfData2Lsb = 1; + byte ElfData2Msb = 2; + int Elf32Addr = Integer.BYTES; + int Elf32Half = Short.BYTES; + int Elf32Off = Integer.BYTES; + int Elf32Sword = Integer.BYTES; + int Elf32Word = Integer.BYTES; + int Elf64Addr = Long.BYTES; + int Elf64Half = Short.BYTES; + int Elf64SHalf = Short.BYTES; + int Elf64Off = Long.BYTES; + int Elf64Sword = Integer.BYTES; + int Elf64Word = Integer.BYTES; + int Elf64Xword = Long.BYTES; + int Elf64Sxword = Long.BYTES; +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java new file mode 100644 index 00000000..b93a1712 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.codesigning.elf; + +import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class ElfFile { + ElfHeader elfHeader; + + List list = new ArrayList<>(); + + public ElfFile(InputStream is) throws IOException, ElfFormatException { + elfHeader = new ElfHeader(is); + byte eiClass = elfHeader.getEiClass(); + byte eiData = elfHeader.getEiData(); + long ePhoff = elfHeader.getE_phoff(); + short ePhnum = elfHeader.getE_phnum(); + + for (short i = 0; i < ePhnum; i++) { + ElfPHeader pHeader = new ElfPHeader(is, eiClass, eiData); + list.add(pHeader); + } + } + + public List filterExecPHeaders() { + return list.stream().filter(phdr -> (phdr.getPFlags() & 1) == 1).collect(Collectors.toList()); + } +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java new file mode 100644 index 00000000..376f54be --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.codesigning.elf; + +import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class ElfHeader { + static final int EI_NIDENT_LEN = 16; + + static final int Elf32_LEN = 36; + + static final int Elf64_LEN = 48; + + byte[] ident = new byte[EI_NIDENT_LEN]; + + private byte eiClass; + + private byte eiData; + + private byte eiVersion; + + private short e_type; + + private int e_machine; + + private int e_version; + + private long e_entry; + + private long e_phoff; + + private long e_shoff; + + private int e_flags; + + private short e_ehsize; + + private short e_phentsize; + + private short e_phnum; + + private short e_shentsize; + + private short e_shnum; + + private short e_shstrndx; + + public ElfHeader(InputStream is) throws IOException, ElfFormatException { + + int read = is.read(ident); + if (read != ident.length || !(ident[0] == 0x7F && ident[1] == 0x45 && ident[2] == 0x4C && ident[3] == 0x46)) { + throw new ElfFormatException("not elf"); + } + eiClass = ident[4]; + eiData = ident[5]; + eiVersion = ident[6]; + if (eiVersion != 1) { + throw new ElfFormatException("not elf"); + } + ByteOrder bo = ByteOrder.LITTLE_ENDIAN; + if (eiData == ElfDefine.ElfData2Lsb) { + bo = ByteOrder.LITTLE_ENDIAN; + } else if (eiData == ElfDefine.ElfData2Msb) { + bo = ByteOrder.BIG_ENDIAN; + } else { + throw new ElfFormatException("not elf"); + } + int len = Elf32_LEN; + if (eiClass == ElfDefine.Elf32Class) { + len = Elf32_LEN; + } else if (eiClass == ElfDefine.Elf64Class) { + len = Elf64_LEN; + } else { + throw new ElfFormatException("not elf"); + } + byte[] bytes = new byte[len]; + is.read(bytes); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + byteBuffer.order(bo); + e_type = byteBuffer.getShort(); + e_machine = byteBuffer.getShort(); + e_version = byteBuffer.getInt(); + + if (eiClass == ElfDefine.Elf32Class) { + e_entry = byteBuffer.getInt() & 0xFFFFFFFFL;// + e_phoff = byteBuffer.getInt() & 0xFFFFFFFFL;// + e_shoff = byteBuffer.getInt() & 0xFFFFFFFFL;// + } else { + e_entry = byteBuffer.getLong();// + e_phoff = byteBuffer.getLong();// + e_shoff = byteBuffer.getLong();// + } + if (e_phoff != size()) { + throw new ElfFormatException("e_phoff error"); + } + e_flags = byteBuffer.getInt(); + e_ehsize = byteBuffer.getShort(); + e_phentsize = byteBuffer.getShort(); + e_phnum = byteBuffer.getShort(); + e_shentsize = byteBuffer.getShort(); + e_shnum = byteBuffer.getShort(); + e_shstrndx = byteBuffer.getShort(); + } + + public byte getEiClass() { + return eiClass; + } + + public byte getEiData() { + return eiData; + } + + public int size() { + return eiClass == ElfDefine.Elf32Class ? Elf32_LEN + ident.length : Elf64_LEN + ident.length; + } + + public long getE_phoff() { + return e_phoff; + } + + public short getE_phnum() { + return e_phnum; + } +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java new file mode 100644 index 00000000..401c1cd7 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.codesigning.elf; + +import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class ElfPHeader { + static final int Elf32_LEN = 32; + + static final int Elf64_LEN = 56; + + private byte eiClass; + + private byte eiData; + + private int p_type; + + private int p_flags; + + private long p_offset; + + private long p_vaddr; + + private long p_paddr; + + private long p_filesz; + + private long p_memsz; + + private long p_align; + + public ElfPHeader(InputStream is, byte eiClass, byte eiData) throws IOException, ElfFormatException { + + ByteOrder bo = ByteOrder.LITTLE_ENDIAN; + if (eiData == ElfDefine.ElfData2Lsb) { + bo = ByteOrder.LITTLE_ENDIAN; + } else if (eiData == ElfDefine.ElfData2Msb) { + bo = ByteOrder.BIG_ENDIAN; + } else { + throw new ElfFormatException("not elf"); + } + if (eiClass == ElfDefine.Elf32Class) { + byte[] bytes = new byte[Elf32_LEN]; + is.read(bytes); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + byteBuffer.order(bo); + p_type = byteBuffer.getInt(); + p_offset = byteBuffer.getInt() & 0xFFFFFFFFL; + p_vaddr = byteBuffer.getInt() & 0xFFFFFFFFL; + p_paddr = byteBuffer.getInt() & 0xFFFFFFFFL; + p_filesz = byteBuffer.getInt(); + p_memsz = byteBuffer.getInt(); + p_flags = byteBuffer.getInt(); + p_align = byteBuffer.getInt(); + } else { + byte[] bytes = new byte[Elf64_LEN]; + is.read(bytes); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + byteBuffer.order(bo); + p_type = byteBuffer.getInt(); + p_flags = byteBuffer.getInt(); + p_offset = byteBuffer.getLong(); + p_vaddr = byteBuffer.getLong(); + p_paddr = byteBuffer.getLong(); + p_filesz = byteBuffer.getLong(); + p_memsz = byteBuffer.getLong(); + p_align = byteBuffer.getLong(); + } + } + + public int getPFlags() { + return p_flags; + } + + public long getPOffset() { + return p_offset; + } + + public long getPFilesz() { + return p_filesz; + } +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java new file mode 100644 index 00000000..34ca1133 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.codesigning.exception; + +public class ElfFormatException extends Exception { + public ElfFormatException(String message) { + super(message); + } + + public ElfFormatException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index 20f238ed..22722c20 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -187,7 +187,8 @@ public class CodeSigning { fsvTreeOffset, ownerID); // update hap segment in CodeSignBlock this.codeSignBlock.getHapInfoSegment().setSignInfo(hapSignInfoAndMerkleTreeBytesPair.getFirst()); - this.codeSignBlock.getHapInfoSegment().getSignInfo().addExtension(new PageInfoExtension(0L, 0L)); + // addPageInfoExtension + addPageInfoExtension(zip); // Insert merkle tree bytes into code sign block this.codeSignBlock.addOneMerkleTree(HAP_SIGNATURE_ENTRY_NAME, hapSignInfoAndMerkleTreeBytesPair.getSecond()); @@ -208,6 +209,25 @@ public class CodeSigning { return generated; } + private void addPageInfoExtension(Zip zip) { + long[] longs = null; + List zipEntries = zip.getZipEntries(); + for (ZipEntry e : zipEntries) { + String fileName = e.getCentralDirectory().getFileName(); + if (!"pages.info".equals(fileName)) { + continue; + } + long fileOffset = e.getZipEntryData().getFileOffset(); + long fileSize = e.getZipEntryData().getFileSize(); + longs = new long[] {fileOffset, fileSize}; + } + if (longs == null) { + return; + } + Extension extension = new PageInfoExtension(longs[0], longs[1]); + this.codeSignBlock.getHapInfoSegment().getSignInfo().addExtension(extension); + } + private long computeDataSize(Zip zip) throws HapFormatException { long dataSize = 0L; for (ZipEntry entry : zip.getZipEntries()) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java new file mode 100644 index 00000000..d33369b7 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.codesigning.sign; + +import com.ohos.hapsigntool.codesigning.datastructure.PageInfoExtension; +import com.ohos.hapsigntool.codesigning.elf.ElfFile; +import com.ohos.hapsigntool.codesigning.elf.ElfPHeader; +import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; +import com.ohos.hapsigntool.entity.Pair; +import com.ohos.hapsigntool.utils.FileUtils; +import com.ohos.hapsigntool.zip.Zip; +import com.ohos.hapsigntool.zip.ZipEntry; +import com.ohos.hapsigntool.zip.ZipEntryHeader; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.FileChannel; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class PageInfoGenerator { + static final byte ABC_M_CODE = 2; + + static final byte ELF_M_CODE = 1; + + public static final long PAGE_SIZE_4K = 4096L; + + public static final long PAGE_SIZE_1K = PAGE_SIZE_4K / PageInfoExtension.DEFAULT_UNIT_SIZE; + + private static final Logger LOGGER = LogManager.getLogger(PageInfoGenerator.class); + + static long maxEntryDataOffset = 0; + + static Map> libexcSegmentMap = new LinkedHashMap(); + + public PageInfoGenerator(File input) throws IOException { + new PageInfoGenerator(new Zip(input)); + } + + public PageInfoGenerator(Zip zip) throws IOException { + Map libNames = new LinkedHashMap<>(); + Map lib1Names = new LinkedHashMap<>(); + + List zipEntries = zip.getZipEntries(); + for (ZipEntry entry : zipEntries) { + ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); + long entryDataOffset = entry.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); + if (entryDataOffset % 4096 != 0) { + break; + } + maxEntryDataOffset = entryDataOffset; + libNames.put(zipEntryHeader.getFileName(), entryDataOffset); + lib1Names.put(entry, entryDataOffset); + } + + File input = new File(zip.getFile()); + long t0 = System.currentTimeMillis(); + + lib1Names.entrySet().stream().parallel().forEach(s -> { + try { + this.libExecSegment1(input, s.getKey(), s.getValue()); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + long t1 = System.currentTimeMillis(); + try (JarFile hap = new JarFile(input, false)) { + libNames.entrySet().forEach(s -> { + try { + this.libExecSegment(hap, s.getKey(), s.getValue()); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + long t3 = System.currentTimeMillis(); + System.out.println("time " + (t1 - t0)); + System.out.println("time " + (t3 - t1)); + } + + void libExecSegment1(File input, ZipEntry entry, long entryDataOffset) throws IOException { + // LOGGER.info(libFileName); + try (FileInputStream fileInputStream = new FileInputStream(input);) { + FileChannel channel = fileInputStream.getChannel(); + long fileOffset = entry.getZipEntryData().getFileOffset(); + // channel.position(fileOffset); + long fileSize = entry.getZipEntryData().getFileSize(); + fileInputStream.skip(fileOffset); + String libFileName = entry.getZipEntryData().getZipEntryHeader().getFileName(); + if (libFileName.endsWith(".abc")) { + libexcSegmentMap.put(libFileName, Pair.create(entryDataOffset, entryDataOffset + fileSize)); + // LOGGER.info(entryDataOffset + " " + (entryDataOffset + size)); + } else if (FileUtils.isRunnableFile(libFileName)) { + ElfFile elfFile = new ElfFile(fileInputStream); + List elfPHeaders = elfFile.filterExecPHeaders(); + for (ElfPHeader programHeader : elfPHeaders) { + long pOffset = programHeader.getPOffset(); + long pFilesz = programHeader.getPFilesz(); + long off = entryDataOffset + pOffset; + long endoff = off + pFilesz; + libexcSegmentMap.put(libFileName, Pair.create(off, endoff)); + // LOGGER.info(off + " " + endoff); + } + } + } catch (ElfFormatException e) { + LOGGER.error(String.format(Locale.ROOT, "Read lib file {%s} error: %s", "libFileName", e.getMessage())); + } + } + + void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) throws IOException { + // LOGGER.info(libFileName); + JarEntry libEntry = hap.getJarEntry(libFileName); + if (libFileName.endsWith(".abc")) { + long size = libEntry.getSize(); + libexcSegmentMap.put(libFileName, Pair.create(entryDataOffset, entryDataOffset + size)); + // LOGGER.info(entryDataOffset + " " + (entryDataOffset + size)); + } else if (FileUtils.isRunnableFile(libFileName)) { + try (InputStream stream = hap.getInputStream(libEntry)) { + ElfFile elfFile = new ElfFile(stream); + List elfPHeaders = elfFile.filterExecPHeaders(); + for (ElfPHeader programHeader : elfPHeaders) { + long pOffset = programHeader.getPOffset(); + long pFilesz = programHeader.getPFilesz(); + long off = entryDataOffset + pOffset; + long endoff = off + pFilesz; + libexcSegmentMap.put(libFileName, Pair.create(off, endoff)); + // LOGGER.info(off + " " + endoff); + } + } catch (ElfFormatException e) { + LOGGER.error(String.format(Locale.ROOT, "Read lib file {%s} error: %s", libFileName, e.getMessage())); + } + } + } + + public byte[] generateBitMap() throws ElfFormatException { + if (maxEntryDataOffset % PAGE_SIZE_4K != 0) { + throw new ElfFormatException( + String.format(Locale.ROOT, "Invalid maxEndOff(%d), not a multiple of 4096", maxEntryDataOffset)); + } + int len = (int) (maxEntryDataOffset / PAGE_SIZE_1K); + byte[] bytes = new byte[len]; + for (Map.Entry> e : libexcSegmentMap.entrySet()) { + String libFileName = e.getKey(); + Pair p = e.getValue(); + int begin = (int) (p.getFirst() / PAGE_SIZE_4K) * 4; + int end = (p.getSecond() % PAGE_SIZE_4K == 0) + ? (int) ((p.getSecond() / PAGE_SIZE_4K)) * 4 + : (int) ((p.getSecond() / PAGE_SIZE_4K) + 1) * 4; + // LOGGER.info(begin + " " + end); + byte b = libFileName.endsWith(".abc") ? ABC_M_CODE : ELF_M_CODE; + for (int i = begin; i < end; i = i + 4) { + bytes[i + 3] = b; + } + } + return bytes; + } + + public static long[] getPageInfo(Zip zip) { + List zipEntries = zip.getZipEntries(); + for (ZipEntry e : zipEntries) { + String fileName = e.getCentralDirectory().getFileName(); + if (!"pages.info".equals(fileName)) { + continue; + } + long fileOffset = e.getZipEntryData().getFileOffset(); + long fileSize = e.getZipEntryData().getFileSize(); + return new long[] {fileOffset, fileSize}; + } + return null; + } +} -- Gitee From 41609dc4939b6ba6309b9a9e0bb375ad1111be51 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Mon, 1 Jul 2024 14:57:52 +0800 Subject: [PATCH 03/26] bitmap generator Signed-off-by: zfeixiang --- .../datastructure/PageInfoExtension.java | 39 +++++++- .../codesigning/elf/ElfDefine.java | 5 + .../hapsigntool/codesigning/elf/ElfFile.java | 19 +++- .../codesigning/elf/ElfHeader.java | 73 ++++++++------- .../codesigning/elf/ElfPHeader.java | 22 +++-- .../codesigning/sign/CodeSigning.java | 12 +-- .../codesigning/sign/PageInfoGenerator.java | 92 ++++--------------- 7 files changed, 133 insertions(+), 129 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java index 131c9a55..5c0109b3 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -18,6 +18,23 @@ package com.ohos.hapsigntool.codesigning.datastructure; import java.nio.ByteBuffer; import java.nio.ByteOrder; +/** + * Pages info extension is a type of Extension to store bitmap file's information, i.e. size and offset, ect. + *

+ * structure + *

+ * 1) u32 type 0x2 + *

+ * 2) u64 mapOffset: the size of bitmap + *

+ * 3) u64 mapSize: offset of the bitmap by the start of the file. + *

+ * 4) u8 unitSize: unit size corresponding to each page, default 4 . + *

+ * 5) u8[7] reserved: + * + * @since 2023/09/08 + */ public class PageInfoExtension extends Extension { /** * Type of PageInfoExtension @@ -25,7 +42,7 @@ public class PageInfoExtension extends Extension { public static final int PAGE_INFO_INLINED = 0x2; /** - * Byte size of PageInfoExtension including merkleTreeSize, offset and root hash. + * Byte size of PageInfoExtension */ public static final int PAGE_INFO_EXTENSION_DATA_SIZE = Extension.EXTENSION_HEADER_SIZE + 24; @@ -43,21 +60,39 @@ public class PageInfoExtension extends Extension { private long mapSize; - private byte unitSize = 4; + private byte unitSize; private byte[] reserved = new byte[RESERVED_SIZE]; + /** + * Constructor for PageInfoExtension + * + * @param mapOffset bitmap offset + * @param mapSize bitmap size + */ public PageInfoExtension(long mapOffset, long mapSize) { super(PAGE_INFO_INLINED, PAGE_INFO_EXTENSION_DATA_SIZE); this.mapOffset = mapOffset; this.mapSize = mapSize; + unitSize = DEFAULT_UNIT_SIZE; } + + /** + * Byte size of PageInfoExtension + * + * @return Byte size of PageInfoExtension + */ @Override public int size() { return PAGE_INFO_EXTENSION_DATA_SIZE; } + /** + * Converts PageInfoExtension to a newly created byte array + * + * @return Byte array representation of PageInfoExtension + */ @Override public byte[] toByteArray() { ByteBuffer bf = ByteBuffer.allocate(PAGE_INFO_EXTENSION_DATA_SIZE).order(ByteOrder.LITTLE_ENDIAN); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java index 1702edaa..db125dd1 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java @@ -15,6 +15,11 @@ package com.ohos.hapsigntool.codesigning.elf; +/** + * ELF struct define + * + * @since 2024/07/01 + */ public interface ElfDefine { byte Elf32Class = 1; byte Elf64Class = 2; diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java index b93a1712..faa6ebf5 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java @@ -23,18 +23,27 @@ import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; +/** + * ELF file + * + * @since 2024/07/01 + */ public class ElfFile { - ElfHeader elfHeader; + private ElfHeader elfHeader; - List list = new ArrayList<>(); + private List list = new ArrayList<>(); + /** + * Constructor for ElfFile + * + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ public ElfFile(InputStream is) throws IOException, ElfFormatException { elfHeader = new ElfHeader(is); byte eiClass = elfHeader.getEiClass(); byte eiData = elfHeader.getEiData(); - long ePhoff = elfHeader.getE_phoff(); - short ePhnum = elfHeader.getE_phnum(); - + short ePhnum = elfHeader.getEPhnum(); for (short i = 0; i < ePhnum; i++) { ElfPHeader pHeader = new ElfPHeader(is, eiClass, eiData); list.add(pHeader); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java index 376f54be..936a5ec8 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java @@ -22,20 +22,25 @@ import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; +/** + * ELF header info + * + * @since 2024/07/01 + */ public class ElfHeader { - static final int EI_NIDENT_LEN = 16; + private static final int EI_NIDENT_LEN = 16; - static final int Elf32_LEN = 36; + private static final int Elf32_LEN = 36; - static final int Elf64_LEN = 48; + private static final int Elf64_LEN = 48; - byte[] ident = new byte[EI_NIDENT_LEN]; + private byte[] ident = new byte[EI_NIDENT_LEN]; - private byte eiClass; + private byte ei_class; - private byte eiData; + private byte ei_data; - private byte eiVersion; + private byte ei_version; private short e_type; @@ -63,33 +68,39 @@ public class ElfHeader { private short e_shstrndx; + /** + * Constructor for ElfHeader + * + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ public ElfHeader(InputStream is) throws IOException, ElfFormatException { int read = is.read(ident); if (read != ident.length || !(ident[0] == 0x7F && ident[1] == 0x45 && ident[2] == 0x4C && ident[3] == 0x46)) { - throw new ElfFormatException("not elf"); - } - eiClass = ident[4]; - eiData = ident[5]; - eiVersion = ident[6]; - if (eiVersion != 1) { - throw new ElfFormatException("not elf"); + return; } - ByteOrder bo = ByteOrder.LITTLE_ENDIAN; - if (eiData == ElfDefine.ElfData2Lsb) { - bo = ByteOrder.LITTLE_ENDIAN; - } else if (eiData == ElfDefine.ElfData2Msb) { - bo = ByteOrder.BIG_ENDIAN; - } else { - throw new ElfFormatException("not elf"); + ei_class = ident[4]; + ei_data = ident[5]; + ei_version = ident[6]; + if (ei_version != 1) { + throw new ElfFormatException("ELF ei_version is incorrect"); } int len = Elf32_LEN; - if (eiClass == ElfDefine.Elf32Class) { + if (ei_class == ElfDefine.Elf32Class) { len = Elf32_LEN; - } else if (eiClass == ElfDefine.Elf64Class) { + } else if (ei_class == ElfDefine.Elf64Class) { len = Elf64_LEN; } else { - throw new ElfFormatException("not elf"); + throw new ElfFormatException("ELF ei_class is incorrect"); + } + ByteOrder bo = ByteOrder.LITTLE_ENDIAN; + if (ei_data == ElfDefine.ElfData2Lsb) { + bo = ByteOrder.LITTLE_ENDIAN; + } else if (ei_data == ElfDefine.ElfData2Msb) { + bo = ByteOrder.BIG_ENDIAN; + } else { + throw new ElfFormatException("ELF ei_data is incorrect"); } byte[] bytes = new byte[len]; is.read(bytes); @@ -99,7 +110,7 @@ public class ElfHeader { e_machine = byteBuffer.getShort(); e_version = byteBuffer.getInt(); - if (eiClass == ElfDefine.Elf32Class) { + if (ei_class == ElfDefine.Elf32Class) { e_entry = byteBuffer.getInt() & 0xFFFFFFFFL;// e_phoff = byteBuffer.getInt() & 0xFFFFFFFFL;// e_shoff = byteBuffer.getInt() & 0xFFFFFFFFL;// @@ -109,7 +120,7 @@ public class ElfHeader { e_shoff = byteBuffer.getLong();// } if (e_phoff != size()) { - throw new ElfFormatException("e_phoff error"); + throw new ElfFormatException("ELF e_phoff is incorrect"); } e_flags = byteBuffer.getInt(); e_ehsize = byteBuffer.getShort(); @@ -121,22 +132,22 @@ public class ElfHeader { } public byte getEiClass() { - return eiClass; + return ei_class; } public byte getEiData() { - return eiData; + return ei_data; } public int size() { - return eiClass == ElfDefine.Elf32Class ? Elf32_LEN + ident.length : Elf64_LEN + ident.length; + return ei_class == ElfDefine.Elf32Class ? Elf32_LEN + ident.length : Elf64_LEN + ident.length; } - public long getE_phoff() { + public long getEPhoff() { return e_phoff; } - public short getE_phnum() { + public short getEPhnum() { return e_phnum; } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java index 401c1cd7..3acae433 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java @@ -22,14 +22,15 @@ import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; +/** + * ELF program header info + * + * @since 2024/07/01 + */ public class ElfPHeader { - static final int Elf32_LEN = 32; - - static final int Elf64_LEN = 56; + private static final int Elf32_LEN = 32; - private byte eiClass; - - private byte eiData; + private static final int Elf64_LEN = 56; private int p_type; @@ -47,15 +48,20 @@ public class ElfPHeader { private long p_align; + /** + * Constructor for ElfPHeader + * + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ public ElfPHeader(InputStream is, byte eiClass, byte eiData) throws IOException, ElfFormatException { - ByteOrder bo = ByteOrder.LITTLE_ENDIAN; if (eiData == ElfDefine.ElfData2Lsb) { bo = ByteOrder.LITTLE_ENDIAN; } else if (eiData == ElfDefine.ElfData2Msb) { bo = ByteOrder.BIG_ENDIAN; } else { - throw new ElfFormatException("not elf"); + throw new ElfFormatException("ELF ei_data is incorrect"); } if (eiClass == ElfDefine.Elf32Class) { byte[] bytes = new byte[Elf32_LEN]; diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index 22722c20..7bc5097a 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -210,17 +210,7 @@ public class CodeSigning { } private void addPageInfoExtension(Zip zip) { - long[] longs = null; - List zipEntries = zip.getZipEntries(); - for (ZipEntry e : zipEntries) { - String fileName = e.getCentralDirectory().getFileName(); - if (!"pages.info".equals(fileName)) { - continue; - } - long fileOffset = e.getZipEntryData().getFileOffset(); - long fileSize = e.getZipEntryData().getFileSize(); - longs = new long[] {fileOffset, fileSize}; - } + long[] longs = PageInfoGenerator.getPageInfoFromZip(zip); if (longs == null) { return; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index d33369b7..8ed6ca7f 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -20,7 +20,6 @@ import com.ohos.hapsigntool.codesigning.elf.ElfFile; import com.ohos.hapsigntool.codesigning.elf.ElfPHeader; import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; import com.ohos.hapsigntool.entity.Pair; -import com.ohos.hapsigntool.utils.FileUtils; import com.ohos.hapsigntool.zip.Zip; import com.ohos.hapsigntool.zip.ZipEntry; import com.ohos.hapsigntool.zip.ZipEntryHeader; @@ -29,10 +28,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.nio.channels.FileChannel; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; @@ -40,104 +37,58 @@ import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; +/** + * pages info bitmap generator + * + * @since 2024/07/01 + */ public class PageInfoGenerator { - static final byte ABC_M_CODE = 2; + private static final byte ABC_M_CODE = 2; - static final byte ELF_M_CODE = 1; + private static final byte ELF_M_CODE = 1; - public static final long PAGE_SIZE_4K = 4096L; + private static final long PAGE_SIZE_4K = 4096L; - public static final long PAGE_SIZE_1K = PAGE_SIZE_4K / PageInfoExtension.DEFAULT_UNIT_SIZE; + private static final long PAGE_SIZE_1K = PAGE_SIZE_4K / PageInfoExtension.DEFAULT_UNIT_SIZE; private static final Logger LOGGER = LogManager.getLogger(PageInfoGenerator.class); - static long maxEntryDataOffset = 0; + private static long maxEntryDataOffset = 0; - static Map> libexcSegmentMap = new LinkedHashMap(); + private static final Map> libexcSegmentMap = new LinkedHashMap<>(); - public PageInfoGenerator(File input) throws IOException { + public PageInfoGenerator(File input) throws IOException, ElfFormatException { new PageInfoGenerator(new Zip(input)); } - public PageInfoGenerator(Zip zip) throws IOException { + public PageInfoGenerator(Zip zip) throws IOException, ElfFormatException { Map libNames = new LinkedHashMap<>(); - Map lib1Names = new LinkedHashMap<>(); - List zipEntries = zip.getZipEntries(); for (ZipEntry entry : zipEntries) { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); long entryDataOffset = entry.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); - if (entryDataOffset % 4096 != 0) { + if (entryDataOffset % PAGE_SIZE_4K != 0) { break; } maxEntryDataOffset = entryDataOffset; libNames.put(zipEntryHeader.getFileName(), entryDataOffset); - lib1Names.put(entry, entryDataOffset); } - File input = new File(zip.getFile()); - long t0 = System.currentTimeMillis(); - - lib1Names.entrySet().stream().parallel().forEach(s -> { - try { - this.libExecSegment1(input, s.getKey(), s.getValue()); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - long t1 = System.currentTimeMillis(); try (JarFile hap = new JarFile(input, false)) { - libNames.entrySet().forEach(s -> { - try { - this.libExecSegment(hap, s.getKey(), s.getValue()); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } - long t3 = System.currentTimeMillis(); - System.out.println("time " + (t1 - t0)); - System.out.println("time " + (t3 - t1)); - } - - void libExecSegment1(File input, ZipEntry entry, long entryDataOffset) throws IOException { - // LOGGER.info(libFileName); - try (FileInputStream fileInputStream = new FileInputStream(input);) { - FileChannel channel = fileInputStream.getChannel(); - long fileOffset = entry.getZipEntryData().getFileOffset(); - // channel.position(fileOffset); - long fileSize = entry.getZipEntryData().getFileSize(); - fileInputStream.skip(fileOffset); - String libFileName = entry.getZipEntryData().getZipEntryHeader().getFileName(); - if (libFileName.endsWith(".abc")) { - libexcSegmentMap.put(libFileName, Pair.create(entryDataOffset, entryDataOffset + fileSize)); - // LOGGER.info(entryDataOffset + " " + (entryDataOffset + size)); - } else if (FileUtils.isRunnableFile(libFileName)) { - ElfFile elfFile = new ElfFile(fileInputStream); - List elfPHeaders = elfFile.filterExecPHeaders(); - for (ElfPHeader programHeader : elfPHeaders) { - long pOffset = programHeader.getPOffset(); - long pFilesz = programHeader.getPFilesz(); - long off = entryDataOffset + pOffset; - long endoff = off + pFilesz; - libexcSegmentMap.put(libFileName, Pair.create(off, endoff)); - // LOGGER.info(off + " " + endoff); - } + for (Map.Entry en : libNames.entrySet()) { + this.libExecSegment(hap, en.getKey(), en.getValue()); } - } catch (ElfFormatException e) { - LOGGER.error(String.format(Locale.ROOT, "Read lib file {%s} error: %s", "libFileName", e.getMessage())); } } - void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) throws IOException { - // LOGGER.info(libFileName); + private void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) + throws IOException, ElfFormatException { JarEntry libEntry = hap.getJarEntry(libFileName); if (libFileName.endsWith(".abc")) { long size = libEntry.getSize(); libexcSegmentMap.put(libFileName, Pair.create(entryDataOffset, entryDataOffset + size)); - // LOGGER.info(entryDataOffset + " " + (entryDataOffset + size)); - } else if (FileUtils.isRunnableFile(libFileName)) { + } else { try (InputStream stream = hap.getInputStream(libEntry)) { ElfFile elfFile = new ElfFile(stream); List elfPHeaders = elfFile.filterExecPHeaders(); @@ -147,10 +98,7 @@ public class PageInfoGenerator { long off = entryDataOffset + pOffset; long endoff = off + pFilesz; libexcSegmentMap.put(libFileName, Pair.create(off, endoff)); - // LOGGER.info(off + " " + endoff); } - } catch (ElfFormatException e) { - LOGGER.error(String.format(Locale.ROOT, "Read lib file {%s} error: %s", libFileName, e.getMessage())); } } } @@ -178,7 +126,7 @@ public class PageInfoGenerator { return bytes; } - public static long[] getPageInfo(Zip zip) { + public static long[] getPageInfoFromZip(Zip zip) { List zipEntries = zip.getZipEntries(); for (ZipEntry e : zipEntries) { String fileName = e.getCentralDirectory().getFileName(); -- Gitee From dd50013e8e23b08d1eadf7f5e7dffc0e51af1361 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Mon, 1 Jul 2024 17:01:02 +0800 Subject: [PATCH 04/26] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/elf/ElfDefine.java | 26 ++-- .../hapsigntool/codesigning/elf/ElfFile.java | 6 + .../codesigning/elf/ElfHeader.java | 135 +++++++++--------- .../codesigning/elf/ElfPHeader.java | 71 +++++---- .../exception/ElfFormatException.java | 5 + .../codesigning/sign/PageInfoGenerator.java | 14 +- 6 files changed, 132 insertions(+), 125 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java index db125dd1..0b19b9c0 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java @@ -21,21 +21,13 @@ package com.ohos.hapsigntool.codesigning.elf; * @since 2024/07/01 */ public interface ElfDefine { - byte Elf32Class = 1; - byte Elf64Class = 2; - byte ElfData2Lsb = 1; - byte ElfData2Msb = 2; - int Elf32Addr = Integer.BYTES; - int Elf32Half = Short.BYTES; - int Elf32Off = Integer.BYTES; - int Elf32Sword = Integer.BYTES; - int Elf32Word = Integer.BYTES; - int Elf64Addr = Long.BYTES; - int Elf64Half = Short.BYTES; - int Elf64SHalf = Short.BYTES; - int Elf64Off = Long.BYTES; - int Elf64Sword = Integer.BYTES; - int Elf64Word = Integer.BYTES; - int Elf64Xword = Long.BYTES; - int Elf64Sxword = Long.BYTES; + byte ELF_32_CLASS = 1; + byte ELF_64_CLASS = 2; + byte ELF_DATA_2_LSB = 1; + byte ELF_DATA_2_MSB = 2; + int ELF_PHEADER_32_LEN = 32; + int ELF_PHEADER_64_LEN = 56; + int EI_NIDENT_LEN = 16; + int ELF_HEADER_32_LEN = EI_NIDENT_LEN + 36; + int ELF_HEADER_64_LEN = EI_NIDENT_LEN + 48; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java index faa6ebf5..444571a6 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java @@ -36,6 +36,7 @@ public class ElfFile { /** * Constructor for ElfFile * + * @param is InputStream * @throws IOException io error * @throws ElfFormatException elf file format error */ @@ -50,6 +51,11 @@ public class ElfFile { } } + /** + * filter executable program segment headers + * + * @return executable program segment headers + */ public List filterExecPHeaders() { return list.stream().filter(phdr -> (phdr.getPFlags() & 1) == 1).collect(Collectors.toList()); } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java index 936a5ec8..680eb7ad 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java @@ -28,126 +28,119 @@ import java.nio.ByteOrder; * @since 2024/07/01 */ public class ElfHeader { - private static final int EI_NIDENT_LEN = 16; + private byte[] ident = new byte[ElfDefine.EI_NIDENT_LEN]; - private static final int Elf32_LEN = 36; + private byte eiClass; - private static final int Elf64_LEN = 48; + private byte eiData; - private byte[] ident = new byte[EI_NIDENT_LEN]; + private byte eiVersion; - private byte ei_class; + private short eType; - private byte ei_data; + private int eMachine; - private byte ei_version; + private int eVersion; - private short e_type; + private long eEntry; - private int e_machine; + private long ePhOff; - private int e_version; + private long eShOff; - private long e_entry; + private int eFlags; - private long e_phoff; + private short eEhSize; - private long e_shoff; + private short ePhEntSize; - private int e_flags; + private short ePhNum; - private short e_ehsize; + private short eShEntSize; - private short e_phentsize; + private short eShNum; - private short e_phnum; - - private short e_shentsize; - - private short e_shnum; - - private short e_shstrndx; + private short eShStrndx; /** * Constructor for ElfHeader * + * @param is InputStream * @throws IOException io error * @throws ElfFormatException elf file format error */ public ElfHeader(InputStream is) throws IOException, ElfFormatException { - - int read = is.read(ident); - if (read != ident.length || !(ident[0] == 0x7F && ident[1] == 0x45 && ident[2] == 0x4C && ident[3] == 0x46)) { + is.read(ident); + if (!(ident[0] == 0x7F && ident[1] == 0x45 && ident[2] == 0x4C && ident[3] == 0x46)) { return; } - ei_class = ident[4]; - ei_data = ident[5]; - ei_version = ident[6]; - if (ei_version != 1) { - throw new ElfFormatException("ELF ei_version is incorrect"); + eiClass = ident[4]; + eiData = ident[5]; + eiVersion = ident[6]; + if (eiVersion != 1) { + throw new ElfFormatException("ELF eiVersion is incorrect"); } - int len = Elf32_LEN; - if (ei_class == ElfDefine.Elf32Class) { - len = Elf32_LEN; - } else if (ei_class == ElfDefine.Elf64Class) { - len = Elf64_LEN; + int len; + if (eiClass == ElfDefine.ELF_32_CLASS) { + len = ElfDefine.ELF_HEADER_32_LEN - ElfDefine.EI_NIDENT_LEN; + } else if (eiClass == ElfDefine.ELF_64_CLASS) { + len = ElfDefine.ELF_HEADER_64_LEN - ElfDefine.EI_NIDENT_LEN; } else { - throw new ElfFormatException("ELF ei_class is incorrect"); + throw new ElfFormatException("ELF eiClass is incorrect"); } - ByteOrder bo = ByteOrder.LITTLE_ENDIAN; - if (ei_data == ElfDefine.ElfData2Lsb) { + ByteOrder bo; + if (eiData == ElfDefine.ELF_DATA_2_LSB) { bo = ByteOrder.LITTLE_ENDIAN; - } else if (ei_data == ElfDefine.ElfData2Msb) { + } else if (eiData == ElfDefine.ELF_DATA_2_MSB) { bo = ByteOrder.BIG_ENDIAN; } else { - throw new ElfFormatException("ELF ei_data is incorrect"); + throw new ElfFormatException("ELF eiData is incorrect"); } byte[] bytes = new byte[len]; is.read(bytes); ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(bo); - e_type = byteBuffer.getShort(); - e_machine = byteBuffer.getShort(); - e_version = byteBuffer.getInt(); - - if (ei_class == ElfDefine.Elf32Class) { - e_entry = byteBuffer.getInt() & 0xFFFFFFFFL;// - e_phoff = byteBuffer.getInt() & 0xFFFFFFFFL;// - e_shoff = byteBuffer.getInt() & 0xFFFFFFFFL;// + eType = byteBuffer.getShort(); + eMachine = byteBuffer.getShort(); + eVersion = byteBuffer.getInt(); + + if (eiClass == ElfDefine.ELF_32_CLASS) { + eEntry = byteBuffer.getInt() & 0xFFFFFFFFL; + ePhOff = byteBuffer.getInt() & 0xFFFFFFFFL; + eShOff = byteBuffer.getInt() & 0xFFFFFFFFL; + if (ePhOff != ElfDefine.ELF_HEADER_32_LEN) { + throw new ElfFormatException("ELF ePhOff is incorrect"); + } } else { - e_entry = byteBuffer.getLong();// - e_phoff = byteBuffer.getLong();// - e_shoff = byteBuffer.getLong();// + eEntry = byteBuffer.getLong(); + ePhOff = byteBuffer.getLong(); + eShOff = byteBuffer.getLong(); + if (ePhOff != ElfDefine.ELF_HEADER_64_LEN) { + throw new ElfFormatException("ELF ePhOff is incorrect"); + } } - if (e_phoff != size()) { - throw new ElfFormatException("ELF e_phoff is incorrect"); - } - e_flags = byteBuffer.getInt(); - e_ehsize = byteBuffer.getShort(); - e_phentsize = byteBuffer.getShort(); - e_phnum = byteBuffer.getShort(); - e_shentsize = byteBuffer.getShort(); - e_shnum = byteBuffer.getShort(); - e_shstrndx = byteBuffer.getShort(); + eFlags = byteBuffer.getInt(); + eEhSize = byteBuffer.getShort(); + ePhEntSize = byteBuffer.getShort(); + ePhNum = byteBuffer.getShort(); + eShEntSize = byteBuffer.getShort(); + eShNum = byteBuffer.getShort(); + eShStrndx = byteBuffer.getShort(); } public byte getEiClass() { - return ei_class; + return eiClass; } public byte getEiData() { - return ei_data; - } - - public int size() { - return ei_class == ElfDefine.Elf32Class ? Elf32_LEN + ident.length : Elf64_LEN + ident.length; + return eiData; } - public long getEPhoff() { - return e_phoff; + public long getEPhOff() { + return ePhOff; } public short getEPhnum() { - return e_phnum; + return ePhNum; } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java index 3acae433..fe6447ca 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java @@ -28,79 +28,78 @@ import java.nio.ByteOrder; * @since 2024/07/01 */ public class ElfPHeader { - private static final int Elf32_LEN = 32; + private int pType; - private static final int Elf64_LEN = 56; + private int pFlags; - private int p_type; + private long pOffset; - private int p_flags; + private long pVaddr; - private long p_offset; + private long pPaddr; - private long p_vaddr; + private long pFilesz; - private long p_paddr; + private long pMemsz; - private long p_filesz; - - private long p_memsz; - - private long p_align; + private long pAlign; /** * Constructor for ElfPHeader * + * @param is InputStream + * @param eiClass eiClass + * @param eiData eiData * @throws IOException io error * @throws ElfFormatException elf file format error */ public ElfPHeader(InputStream is, byte eiClass, byte eiData) throws IOException, ElfFormatException { ByteOrder bo = ByteOrder.LITTLE_ENDIAN; - if (eiData == ElfDefine.ElfData2Lsb) { + if (eiData == ElfDefine.ELF_DATA_2_LSB) { bo = ByteOrder.LITTLE_ENDIAN; - } else if (eiData == ElfDefine.ElfData2Msb) { + } else if (eiData == ElfDefine.ELF_DATA_2_MSB) { bo = ByteOrder.BIG_ENDIAN; } else { throw new ElfFormatException("ELF ei_data is incorrect"); } - if (eiClass == ElfDefine.Elf32Class) { - byte[] bytes = new byte[Elf32_LEN]; + if (eiClass == ElfDefine.ELF_32_CLASS) { + byte[] bytes = new byte[ElfDefine.ELF_PHEADER_32_LEN]; is.read(bytes); ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(bo); - p_type = byteBuffer.getInt(); - p_offset = byteBuffer.getInt() & 0xFFFFFFFFL; - p_vaddr = byteBuffer.getInt() & 0xFFFFFFFFL; - p_paddr = byteBuffer.getInt() & 0xFFFFFFFFL; - p_filesz = byteBuffer.getInt(); - p_memsz = byteBuffer.getInt(); - p_flags = byteBuffer.getInt(); - p_align = byteBuffer.getInt(); + pType = byteBuffer.getInt(); + pOffset = byteBuffer.getInt() & 0xFFFFFFFFL; + pVaddr = byteBuffer.getInt() & 0xFFFFFFFFL; + pPaddr = byteBuffer.getInt() & 0xFFFFFFFFL; + pFilesz = byteBuffer.getInt(); + pMemsz = byteBuffer.getInt(); + pFlags = byteBuffer.getInt(); + pAlign = byteBuffer.getInt(); } else { - byte[] bytes = new byte[Elf64_LEN]; + byte[] bytes = new byte[ElfDefine.ELF_PHEADER_64_LEN]; is.read(bytes); ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(bo); - p_type = byteBuffer.getInt(); - p_flags = byteBuffer.getInt(); - p_offset = byteBuffer.getLong(); - p_vaddr = byteBuffer.getLong(); - p_paddr = byteBuffer.getLong(); - p_filesz = byteBuffer.getLong(); - p_memsz = byteBuffer.getLong(); - p_align = byteBuffer.getLong(); + pType = byteBuffer.getInt(); + pFlags = byteBuffer.getInt(); + pOffset = byteBuffer.getLong(); + pVaddr = byteBuffer.getLong(); + pPaddr = byteBuffer.getLong(); + pFilesz = byteBuffer.getLong(); + pMemsz = byteBuffer.getLong(); + pAlign = byteBuffer.getLong(); } } public int getPFlags() { - return p_flags; + return pFlags; } public long getPOffset() { - return p_offset; + return pOffset; } public long getPFilesz() { - return p_filesz; + return pFilesz; } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java index 34ca1133..1089f073 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java @@ -15,6 +15,11 @@ package com.ohos.hapsigntool.codesigning.exception; +/** + * Elf format exception + * + * @since 2024/07/01 + */ public class ElfFormatException extends Exception { public ElfFormatException(String message) { super(message); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index 8ed6ca7f..c9b3ce21 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -53,14 +53,26 @@ public class PageInfoGenerator { private static final Logger LOGGER = LogManager.getLogger(PageInfoGenerator.class); - private static long maxEntryDataOffset = 0; + private static long maxEntryDataOffset = 0L; private static final Map> libexcSegmentMap = new LinkedHashMap<>(); + /** + * Constructor for PageInfoGenerator + * + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ public PageInfoGenerator(File input) throws IOException, ElfFormatException { new PageInfoGenerator(new Zip(input)); } + /** + * Constructor for PageInfoGenerator + * + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ public PageInfoGenerator(Zip zip) throws IOException, ElfFormatException { Map libNames = new LinkedHashMap<>(); List zipEntries = zip.getZipEntries(); -- Gitee From cfb349f1d625bd0faae0e6dad946319c63d5eeac Mon Sep 17 00:00:00 2001 From: zhanzeyi Date: Wed, 3 Jul 2024 10:27:25 +0800 Subject: [PATCH 05/26] add zip bitmap codesign Signed-off-by: zhanzeyi --- .../hapsigntool/zip/CentralDirectory.java | 9 +- .../com/ohos/hapsigntool/zip/EntryType.java | 26 +++ .../java/com/ohos/hapsigntool/zip/Zip.java | 51 ++++-- .../com/ohos/hapsigntool/zip/ZipEntry.java | 164 ++++++++++++++++-- .../ohos/hapsigntool/zip/ZipEntryData.java | 32 ++++ .../ohos/hapsigntool/zip/ZipEntryHeader.java | 9 +- 6 files changed, 264 insertions(+), 27 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java index 04adc9b4..37e8d1d0 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java @@ -155,6 +155,13 @@ public class CentralDirectory { private int length; + /** + * updateLength + */ + public void updateLength() { + length = CD_LENGTH + fileNameLength + extraLength + commentLength; + } + /** * get Central Directory * @@ -199,7 +206,7 @@ public class CentralDirectory { bf.get(readComment); cd.setComment(readComment); } - cd.setLength(CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength()); + cd.updateLength(); return cd; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java new file mode 100644 index 00000000..46d44b13 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ohos.hapsigntool.zip; + +/** + * Entry Type + * + * @since 2024/06/25 + */ +public enum EntryType { + RunnableFile, + BitMap, + ResourceFile; +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index 7ab9bdc2..e1a43b20 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -19,7 +19,6 @@ import com.ohos.hapsigntool.error.CustomException; import com.ohos.hapsigntool.error.ERROR; import com.ohos.hapsigntool.error.ZipException; import com.ohos.hapsigntool.utils.FileUtils; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -43,7 +42,7 @@ public class Zip { /** * file is uncompress file flag */ - public static final int FILE_UNCOMPRESS_METHOD_FLAG = 0; + public static final short FILE_UNCOMPRESS_METHOD_FLAG = 0; /** * max comment length @@ -172,6 +171,12 @@ public class Zip { long fileSize = cd.getMethod() == FILE_UNCOMPRESS_METHOD_FLAG ? unCompressedSize : compressedSize; ZipEntryData zipEntryData = ZipEntryData.getZipEntry(file, offset, fileSize); + if (zipEntryData.getZipEntryHeader().getMethod() == FILE_UNCOMPRESS_METHOD_FLAG + && FileUtils.isRunnableFile(zipEntryData.getZipEntryHeader().getFileName())) { + zipEntryData.setType(EntryType.RunnableFile); + } else { + zipEntryData.setType(EntryType.ResourceFile); + } if (cDOffset - offset < zipEntryData.getLength()) { throw new ZipException("cd offset in front of entry end"); } @@ -189,8 +194,15 @@ public class Zip { for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), fos); - boolean isSuccess = FileUtils.appendWriteFileByOffsetToFile(file, fos, - zipEntryData.getFileOffset(), zipEntryData.getFileSize()); + boolean isSuccess; + if (entry.getZipEntryData().getType() == EntryType.BitMap) { + ByteBuffer bf = ByteBuffer.wrap(entry.getZipEntryData().getData()); + bf.order(ByteOrder.LITTLE_ENDIAN); + isSuccess = FileUtils.writeByteToOutFile(bf.array(), fos); + } else { + isSuccess = FileUtils.appendWriteFileByOffsetToFile(file, fos, + zipEntryData.getFileOffset(), zipEntryData.getFileSize()); + } if (!isSuccess) { throw new ZipException("write zip data failed"); } @@ -250,6 +262,16 @@ public class Zip { } } + public void addBitMap(byte[] data) throws ZipException { + ZipEntry entry = new ZipEntry.Builder().setMethod(FILE_UNCOMPRESS_METHOD_FLAG) + .setUncompressedSize(data.length) + .setCompressedSize(data.length) + .setFileName("pages.info") + .setData(data) + .build(); + zipEntries.add(entry); + } + /** * remove sign block */ @@ -262,22 +284,20 @@ public class Zip { * sort uncompress entry in the front. */ private void sort() { - // sort uncompress file (so, abc, an) - other uncompress file - compress file + // sort uncompress file (so, abc, an) - bitmap - other uncompress file - compress file zipEntries.sort((entry1, entry2) -> { + EntryType entry1Type = entry1.getZipEntryData().getType(); + EntryType entry2Type = entry2.getZipEntryData().getType(); + if (entry1Type != entry2Type) { + return entry1Type.compareTo(entry2Type); + } + short entry1Method = entry1.getZipEntryData().getZipEntryHeader().getMethod(); short entry2Method = entry2.getZipEntryData().getZipEntryHeader().getMethod(); String entry1FileName = entry1.getZipEntryData().getZipEntryHeader().getFileName(); String entry2FileName = entry2.getZipEntryData().getZipEntryHeader().getFileName(); if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG && entry2Method == FILE_UNCOMPRESS_METHOD_FLAG) { - boolean isRunnableFile1 = FileUtils.isRunnableFile(entry1FileName); - boolean isRunnableFile2 = FileUtils.isRunnableFile(entry2FileName); - if (isRunnableFile1 && isRunnableFile2) { - return entry1FileName.compareTo(entry2FileName); - } else if (isRunnableFile1) { - return -1; - } else if (isRunnableFile2) { - return 1; - } + return entry1FileName.compareTo(entry2FileName); } else if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG) { return -1; } else if (entry2Method == FILE_UNCOMPRESS_METHOD_FLAG) { @@ -292,6 +312,7 @@ public class Zip { long offset = 0L; long cdLength = 0L; for (ZipEntry entry : zipEntries) { + entry.updateLength(); entry.getCentralDirectory().setOffset(offset); offset += entry.getZipEntryData().getLength(); cdLength += entry.getCentralDirectory().getLength(); @@ -304,6 +325,8 @@ public class Zip { endOfCentralDirectory.setcDSize(cdLength); offset += cdLength; eOCDOffset = offset; + endOfCentralDirectory.setcDTotal(zipEntries.size()); + endOfCentralDirectory.setThisDiskCDNum(zipEntries.size()); } public List getZipEntries() { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java index ff66339a..82d7a2fb 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java @@ -18,6 +18,7 @@ package com.ohos.hapsigntool.zip; import com.ohos.hapsigntool.error.ZipException; import java.util.Arrays; +import java.util.zip.CRC32; /** * ZipEntry and CentralDirectory data @@ -27,7 +28,15 @@ import java.util.Arrays; public class ZipEntry { private ZipEntryData zipEntryData; - private CentralDirectory fileEntryIncentralDirectory; + private CentralDirectory fileEntryInCentralDirectory; + + /** + * updateLength + */ + public void updateLength() { + zipEntryData.updateLength(); + fileEntryInCentralDirectory.updateLength(); + } /** * alignment one entry @@ -40,7 +49,7 @@ public class ZipEntry { // if cd extra len bigger than entry extra len, make cd and entry extra length equals int padding = calZeroPaddingLengthForEntryExtra(); int remainder = (int) ((zipEntryData.getZipEntryHeader().getLength() - + fileEntryIncentralDirectory.getOffset()) % alignNum); + + fileEntryInCentralDirectory.getOffset()) % alignNum); if (remainder == 0) { return padding; @@ -58,7 +67,7 @@ public class ZipEntry { private int calZeroPaddingLengthForEntryExtra() throws ZipException { int entryExtraLen = zipEntryData.getZipEntryHeader().getExtraLength(); - int cdExtraLen = fileEntryIncentralDirectory.getExtraLength(); + int cdExtraLen = fileEntryInCentralDirectory.getExtraLength(); if (cdExtraLen > entryExtraLen) { setEntryHeaderNewExtraLength(cdExtraLen); return cdExtraLen - entryExtraLen; @@ -71,12 +80,12 @@ public class ZipEntry { } private void setCenterDirectoryNewExtraLength(int newLength) throws ZipException { - byte[] newCDExtra = getAlignmentNewExtra(newLength, fileEntryIncentralDirectory.getExtraData()); - fileEntryIncentralDirectory.setExtraData(newCDExtra); - fileEntryIncentralDirectory.setExtraLength(newLength); - fileEntryIncentralDirectory.setLength(CentralDirectory.CD_LENGTH - + fileEntryIncentralDirectory.getFileNameLength() - + fileEntryIncentralDirectory.getExtraLength() + fileEntryIncentralDirectory.getCommentLength()); + byte[] newCDExtra = getAlignmentNewExtra(newLength, fileEntryInCentralDirectory.getExtraData()); + fileEntryInCentralDirectory.setExtraData(newCDExtra); + fileEntryInCentralDirectory.setExtraLength(newLength); + fileEntryInCentralDirectory.setLength(CentralDirectory.CD_LENGTH + + fileEntryInCentralDirectory.getFileNameLength() + + fileEntryInCentralDirectory.getExtraLength() + fileEntryInCentralDirectory.getCommentLength()); } private void setEntryHeaderNewExtraLength(int newLength) throws ZipException { @@ -109,10 +118,143 @@ public class ZipEntry { } public CentralDirectory getCentralDirectory() { - return fileEntryIncentralDirectory; + return fileEntryInCentralDirectory; } public void setCentralDirectory(CentralDirectory centralDirectory) { - this.fileEntryIncentralDirectory = centralDirectory; + this.fileEntryInCentralDirectory = centralDirectory; + } + + public static class Builder { + private short version = 10; + + private short flag = 2048; + + private short method = 0; + + private long compressedSize; + + private long unCompressedSize; + + private String fileName; + + private byte[] extraData; + + private byte[] comment; + + private byte[] data; + + public Builder setVersion(short version) { + this.version = version; + return this; + } + + public Builder setFlag(short flag) { + this.flag = flag; + return this; + } + + public Builder setMethod(short method) { + this.method = method; + return this; + } + + public Builder setCompressedSize(long compressedSize) { + this.compressedSize = compressedSize; + return this; + } + + public Builder setUncompressedSize(long unCompressedSize) { + this.unCompressedSize = unCompressedSize; + return this; + } + + public Builder setFileName(String fileName) { + this.fileName = fileName; + return this; + } + + public Builder setExtraData(byte[] extraData) { + this.extraData = extraData; + return this; + } + + public Builder setComment(byte[] comment) { + this.comment = comment; + return this; + } + + public Builder setData(byte[] data) { + this.data = data; + return this; + } + + public ZipEntry build() throws ZipException { + ZipEntry entry = new ZipEntry(); + ZipEntryData zipEntryData = new ZipEntryData(); + zipEntryData.setData(data); + + ZipEntryHeader zipEntryHeader = new ZipEntryHeader(); + CentralDirectory cd = new CentralDirectory(); + + cd.setVersion(version); + cd.setVersionExtra(version); + zipEntryHeader.setVersion(version); + cd.setFlag(flag); + zipEntryHeader.setFlag(flag); + cd.setMethod(method); + zipEntryHeader.setMethod(method); + + cd.setLastTime((short) 0); + cd.setLastDate((short) 20001); + zipEntryHeader.setLastTime((short) 0); + zipEntryHeader.setLastDate((short) 20001); + + cd.setCompressedSize(compressedSize); + zipEntryHeader.setCompressedSize(compressedSize); + cd.setUnCompressedSize(unCompressedSize); + zipEntryHeader.setUnCompressedSize(unCompressedSize); + + cd.setFileName(fileName); + cd.setFileNameLength(fileName.length()); + zipEntryHeader.setFileName(fileName); + zipEntryHeader.setFileNameLength(fileName.length()); + + if (extraData != null) { + cd.setExtraData(extraData); + cd.setExtraLength(extraData.length); + zipEntryHeader.setExtraData(extraData); + zipEntryHeader.setExtraLength(extraData.length); + } else { + cd.setExtraLength(0); + zipEntryHeader.setExtraLength(0); + } + if (comment != null) { + cd.setComment(comment); + cd.setCommentLength(comment.length); + } else { + cd.setCommentLength(0); + } + cd.setDiskNumStart(0); + cd.setExternalFile(0); + + cd.updateLength(); + zipEntryHeader.updateLength(); + + if (data == null) { + throw new ZipException("can not find entry data"); + } + final CRC32 c = new CRC32(); + c.update(data); + final int crc32 = new Long(c.getValue()).intValue(); + cd.setCrc32(crc32); + zipEntryHeader.setCrc32(crc32); + + zipEntryData.setZipEntryHeader(zipEntryHeader); + entry.setZipEntryData(zipEntryData); + zipEntryData.setType(EntryType.BitMap); + entry.setCentralDirectory(cd); + return entry; + } } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java index 35b19e7a..4007be31 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java @@ -51,6 +51,22 @@ public class ZipEntryData { return zipEntryHeader; } + private EntryType type; + + private byte[] data; + + /** + * updateLength + */ + public void updateLength() { + zipEntryHeader.updateLength(); + if (type == EntryType.BitMap) { + length = zipEntryHeader.getLength() + data.length + (dataDescriptor == null ? 0 : 16); + } else { + length = zipEntryHeader.getLength() + fileSize + (dataDescriptor == null ? 0 : 16); + } + } + /** * init zip entry by file * @@ -140,4 +156,20 @@ public class ZipEntryData { public void setLength(long length) { this.length = length; } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public EntryType getType() { + return type; + } + + public void setType(EntryType type) { + this.type = type; + } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java index 7c880a6b..d020c8fa 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java @@ -113,6 +113,13 @@ public class ZipEntryHeader { private int length; + /** + * updateLength + */ + public void updateLength() { + length = HEADER_LENGTH + fileNameLength + extraLength; + } + /** * get Zip Entry Header * @@ -137,7 +144,7 @@ public class ZipEntryHeader { entryHeader.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); entryHeader.setFileNameLength(UnsignedDecimalUtil.getUnsignedShort(bf)); entryHeader.setExtraLength(UnsignedDecimalUtil.getUnsignedShort(bf)); - entryHeader.setLength(HEADER_LENGTH + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); + entryHeader.updateLength(); return entryHeader; } -- Gitee From 3b9f5d0450998c8e4f4e38d1e9c74bc44ca16904 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Wed, 3 Jul 2024 02:31:06 +0000 Subject: [PATCH 06/26] Revert "add zip bitmap codesign" This reverts commit cfb349f1d625bd0faae0e6dad946319c63d5eeac. --- .../hapsigntool/zip/CentralDirectory.java | 9 +- .../com/ohos/hapsigntool/zip/EntryType.java | 26 --- .../java/com/ohos/hapsigntool/zip/Zip.java | 51 ++---- .../com/ohos/hapsigntool/zip/ZipEntry.java | 164 ++---------------- .../ohos/hapsigntool/zip/ZipEntryData.java | 32 ---- .../ohos/hapsigntool/zip/ZipEntryHeader.java | 9 +- 6 files changed, 27 insertions(+), 264 deletions(-) delete mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java index 37e8d1d0..04adc9b4 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java @@ -155,13 +155,6 @@ public class CentralDirectory { private int length; - /** - * updateLength - */ - public void updateLength() { - length = CD_LENGTH + fileNameLength + extraLength + commentLength; - } - /** * get Central Directory * @@ -206,7 +199,7 @@ public class CentralDirectory { bf.get(readComment); cd.setComment(readComment); } - cd.updateLength(); + cd.setLength(CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength()); return cd; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java deleted file mode 100644 index 46d44b13..00000000 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2024-2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.ohos.hapsigntool.zip; - -/** - * Entry Type - * - * @since 2024/06/25 - */ -public enum EntryType { - RunnableFile, - BitMap, - ResourceFile; -} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index e1a43b20..7ab9bdc2 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -19,6 +19,7 @@ import com.ohos.hapsigntool.error.CustomException; import com.ohos.hapsigntool.error.ERROR; import com.ohos.hapsigntool.error.ZipException; import com.ohos.hapsigntool.utils.FileUtils; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -42,7 +43,7 @@ public class Zip { /** * file is uncompress file flag */ - public static final short FILE_UNCOMPRESS_METHOD_FLAG = 0; + public static final int FILE_UNCOMPRESS_METHOD_FLAG = 0; /** * max comment length @@ -171,12 +172,6 @@ public class Zip { long fileSize = cd.getMethod() == FILE_UNCOMPRESS_METHOD_FLAG ? unCompressedSize : compressedSize; ZipEntryData zipEntryData = ZipEntryData.getZipEntry(file, offset, fileSize); - if (zipEntryData.getZipEntryHeader().getMethod() == FILE_UNCOMPRESS_METHOD_FLAG - && FileUtils.isRunnableFile(zipEntryData.getZipEntryHeader().getFileName())) { - zipEntryData.setType(EntryType.RunnableFile); - } else { - zipEntryData.setType(EntryType.ResourceFile); - } if (cDOffset - offset < zipEntryData.getLength()) { throw new ZipException("cd offset in front of entry end"); } @@ -194,15 +189,8 @@ public class Zip { for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), fos); - boolean isSuccess; - if (entry.getZipEntryData().getType() == EntryType.BitMap) { - ByteBuffer bf = ByteBuffer.wrap(entry.getZipEntryData().getData()); - bf.order(ByteOrder.LITTLE_ENDIAN); - isSuccess = FileUtils.writeByteToOutFile(bf.array(), fos); - } else { - isSuccess = FileUtils.appendWriteFileByOffsetToFile(file, fos, - zipEntryData.getFileOffset(), zipEntryData.getFileSize()); - } + boolean isSuccess = FileUtils.appendWriteFileByOffsetToFile(file, fos, + zipEntryData.getFileOffset(), zipEntryData.getFileSize()); if (!isSuccess) { throw new ZipException("write zip data failed"); } @@ -262,16 +250,6 @@ public class Zip { } } - public void addBitMap(byte[] data) throws ZipException { - ZipEntry entry = new ZipEntry.Builder().setMethod(FILE_UNCOMPRESS_METHOD_FLAG) - .setUncompressedSize(data.length) - .setCompressedSize(data.length) - .setFileName("pages.info") - .setData(data) - .build(); - zipEntries.add(entry); - } - /** * remove sign block */ @@ -284,20 +262,22 @@ public class Zip { * sort uncompress entry in the front. */ private void sort() { - // sort uncompress file (so, abc, an) - bitmap - other uncompress file - compress file + // sort uncompress file (so, abc, an) - other uncompress file - compress file zipEntries.sort((entry1, entry2) -> { - EntryType entry1Type = entry1.getZipEntryData().getType(); - EntryType entry2Type = entry2.getZipEntryData().getType(); - if (entry1Type != entry2Type) { - return entry1Type.compareTo(entry2Type); - } - short entry1Method = entry1.getZipEntryData().getZipEntryHeader().getMethod(); short entry2Method = entry2.getZipEntryData().getZipEntryHeader().getMethod(); String entry1FileName = entry1.getZipEntryData().getZipEntryHeader().getFileName(); String entry2FileName = entry2.getZipEntryData().getZipEntryHeader().getFileName(); if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG && entry2Method == FILE_UNCOMPRESS_METHOD_FLAG) { - return entry1FileName.compareTo(entry2FileName); + boolean isRunnableFile1 = FileUtils.isRunnableFile(entry1FileName); + boolean isRunnableFile2 = FileUtils.isRunnableFile(entry2FileName); + if (isRunnableFile1 && isRunnableFile2) { + return entry1FileName.compareTo(entry2FileName); + } else if (isRunnableFile1) { + return -1; + } else if (isRunnableFile2) { + return 1; + } } else if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG) { return -1; } else if (entry2Method == FILE_UNCOMPRESS_METHOD_FLAG) { @@ -312,7 +292,6 @@ public class Zip { long offset = 0L; long cdLength = 0L; for (ZipEntry entry : zipEntries) { - entry.updateLength(); entry.getCentralDirectory().setOffset(offset); offset += entry.getZipEntryData().getLength(); cdLength += entry.getCentralDirectory().getLength(); @@ -325,8 +304,6 @@ public class Zip { endOfCentralDirectory.setcDSize(cdLength); offset += cdLength; eOCDOffset = offset; - endOfCentralDirectory.setcDTotal(zipEntries.size()); - endOfCentralDirectory.setThisDiskCDNum(zipEntries.size()); } public List getZipEntries() { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java index 82d7a2fb..ff66339a 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java @@ -18,7 +18,6 @@ package com.ohos.hapsigntool.zip; import com.ohos.hapsigntool.error.ZipException; import java.util.Arrays; -import java.util.zip.CRC32; /** * ZipEntry and CentralDirectory data @@ -28,15 +27,7 @@ import java.util.zip.CRC32; public class ZipEntry { private ZipEntryData zipEntryData; - private CentralDirectory fileEntryInCentralDirectory; - - /** - * updateLength - */ - public void updateLength() { - zipEntryData.updateLength(); - fileEntryInCentralDirectory.updateLength(); - } + private CentralDirectory fileEntryIncentralDirectory; /** * alignment one entry @@ -49,7 +40,7 @@ public class ZipEntry { // if cd extra len bigger than entry extra len, make cd and entry extra length equals int padding = calZeroPaddingLengthForEntryExtra(); int remainder = (int) ((zipEntryData.getZipEntryHeader().getLength() - + fileEntryInCentralDirectory.getOffset()) % alignNum); + + fileEntryIncentralDirectory.getOffset()) % alignNum); if (remainder == 0) { return padding; @@ -67,7 +58,7 @@ public class ZipEntry { private int calZeroPaddingLengthForEntryExtra() throws ZipException { int entryExtraLen = zipEntryData.getZipEntryHeader().getExtraLength(); - int cdExtraLen = fileEntryInCentralDirectory.getExtraLength(); + int cdExtraLen = fileEntryIncentralDirectory.getExtraLength(); if (cdExtraLen > entryExtraLen) { setEntryHeaderNewExtraLength(cdExtraLen); return cdExtraLen - entryExtraLen; @@ -80,12 +71,12 @@ public class ZipEntry { } private void setCenterDirectoryNewExtraLength(int newLength) throws ZipException { - byte[] newCDExtra = getAlignmentNewExtra(newLength, fileEntryInCentralDirectory.getExtraData()); - fileEntryInCentralDirectory.setExtraData(newCDExtra); - fileEntryInCentralDirectory.setExtraLength(newLength); - fileEntryInCentralDirectory.setLength(CentralDirectory.CD_LENGTH - + fileEntryInCentralDirectory.getFileNameLength() - + fileEntryInCentralDirectory.getExtraLength() + fileEntryInCentralDirectory.getCommentLength()); + byte[] newCDExtra = getAlignmentNewExtra(newLength, fileEntryIncentralDirectory.getExtraData()); + fileEntryIncentralDirectory.setExtraData(newCDExtra); + fileEntryIncentralDirectory.setExtraLength(newLength); + fileEntryIncentralDirectory.setLength(CentralDirectory.CD_LENGTH + + fileEntryIncentralDirectory.getFileNameLength() + + fileEntryIncentralDirectory.getExtraLength() + fileEntryIncentralDirectory.getCommentLength()); } private void setEntryHeaderNewExtraLength(int newLength) throws ZipException { @@ -118,143 +109,10 @@ public class ZipEntry { } public CentralDirectory getCentralDirectory() { - return fileEntryInCentralDirectory; + return fileEntryIncentralDirectory; } public void setCentralDirectory(CentralDirectory centralDirectory) { - this.fileEntryInCentralDirectory = centralDirectory; - } - - public static class Builder { - private short version = 10; - - private short flag = 2048; - - private short method = 0; - - private long compressedSize; - - private long unCompressedSize; - - private String fileName; - - private byte[] extraData; - - private byte[] comment; - - private byte[] data; - - public Builder setVersion(short version) { - this.version = version; - return this; - } - - public Builder setFlag(short flag) { - this.flag = flag; - return this; - } - - public Builder setMethod(short method) { - this.method = method; - return this; - } - - public Builder setCompressedSize(long compressedSize) { - this.compressedSize = compressedSize; - return this; - } - - public Builder setUncompressedSize(long unCompressedSize) { - this.unCompressedSize = unCompressedSize; - return this; - } - - public Builder setFileName(String fileName) { - this.fileName = fileName; - return this; - } - - public Builder setExtraData(byte[] extraData) { - this.extraData = extraData; - return this; - } - - public Builder setComment(byte[] comment) { - this.comment = comment; - return this; - } - - public Builder setData(byte[] data) { - this.data = data; - return this; - } - - public ZipEntry build() throws ZipException { - ZipEntry entry = new ZipEntry(); - ZipEntryData zipEntryData = new ZipEntryData(); - zipEntryData.setData(data); - - ZipEntryHeader zipEntryHeader = new ZipEntryHeader(); - CentralDirectory cd = new CentralDirectory(); - - cd.setVersion(version); - cd.setVersionExtra(version); - zipEntryHeader.setVersion(version); - cd.setFlag(flag); - zipEntryHeader.setFlag(flag); - cd.setMethod(method); - zipEntryHeader.setMethod(method); - - cd.setLastTime((short) 0); - cd.setLastDate((short) 20001); - zipEntryHeader.setLastTime((short) 0); - zipEntryHeader.setLastDate((short) 20001); - - cd.setCompressedSize(compressedSize); - zipEntryHeader.setCompressedSize(compressedSize); - cd.setUnCompressedSize(unCompressedSize); - zipEntryHeader.setUnCompressedSize(unCompressedSize); - - cd.setFileName(fileName); - cd.setFileNameLength(fileName.length()); - zipEntryHeader.setFileName(fileName); - zipEntryHeader.setFileNameLength(fileName.length()); - - if (extraData != null) { - cd.setExtraData(extraData); - cd.setExtraLength(extraData.length); - zipEntryHeader.setExtraData(extraData); - zipEntryHeader.setExtraLength(extraData.length); - } else { - cd.setExtraLength(0); - zipEntryHeader.setExtraLength(0); - } - if (comment != null) { - cd.setComment(comment); - cd.setCommentLength(comment.length); - } else { - cd.setCommentLength(0); - } - cd.setDiskNumStart(0); - cd.setExternalFile(0); - - cd.updateLength(); - zipEntryHeader.updateLength(); - - if (data == null) { - throw new ZipException("can not find entry data"); - } - final CRC32 c = new CRC32(); - c.update(data); - final int crc32 = new Long(c.getValue()).intValue(); - cd.setCrc32(crc32); - zipEntryHeader.setCrc32(crc32); - - zipEntryData.setZipEntryHeader(zipEntryHeader); - entry.setZipEntryData(zipEntryData); - zipEntryData.setType(EntryType.BitMap); - entry.setCentralDirectory(cd); - return entry; - } + this.fileEntryIncentralDirectory = centralDirectory; } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java index 4007be31..35b19e7a 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java @@ -51,22 +51,6 @@ public class ZipEntryData { return zipEntryHeader; } - private EntryType type; - - private byte[] data; - - /** - * updateLength - */ - public void updateLength() { - zipEntryHeader.updateLength(); - if (type == EntryType.BitMap) { - length = zipEntryHeader.getLength() + data.length + (dataDescriptor == null ? 0 : 16); - } else { - length = zipEntryHeader.getLength() + fileSize + (dataDescriptor == null ? 0 : 16); - } - } - /** * init zip entry by file * @@ -156,20 +140,4 @@ public class ZipEntryData { public void setLength(long length) { this.length = length; } - - public byte[] getData() { - return data; - } - - public void setData(byte[] data) { - this.data = data; - } - - public EntryType getType() { - return type; - } - - public void setType(EntryType type) { - this.type = type; - } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java index d020c8fa..7c880a6b 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java @@ -113,13 +113,6 @@ public class ZipEntryHeader { private int length; - /** - * updateLength - */ - public void updateLength() { - length = HEADER_LENGTH + fileNameLength + extraLength; - } - /** * get Zip Entry Header * @@ -144,7 +137,7 @@ public class ZipEntryHeader { entryHeader.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); entryHeader.setFileNameLength(UnsignedDecimalUtil.getUnsignedShort(bf)); entryHeader.setExtraLength(UnsignedDecimalUtil.getUnsignedShort(bf)); - entryHeader.updateLength(); + entryHeader.setLength(HEADER_LENGTH + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); return entryHeader; } -- Gitee From e7d59a0324fc2777603c5b7ce8d244e37259c791 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Wed, 3 Jul 2024 10:31:49 +0800 Subject: [PATCH 07/26] add zip bitmap codesign Signed-off-by: wangzeyu --- .../hap/provider/SignProvider.java | 1 + .../hapsigntool/zip/CentralDirectory.java | 9 +- .../com/ohos/hapsigntool/zip/EntryType.java | 26 +++ .../java/com/ohos/hapsigntool/zip/Zip.java | 51 ++++-- .../com/ohos/hapsigntool/zip/ZipEntry.java | 164 ++++++++++++++++-- .../ohos/hapsigntool/zip/ZipEntryData.java | 32 ++++ .../ohos/hapsigntool/zip/ZipEntryHeader.java | 9 +- 7 files changed, 265 insertions(+), 27 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index edf3bf6e..a58fb5c9 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -500,6 +500,7 @@ public abstract class SignProvider { * @return zip zip * @throws IOException io error * @throws HapFormatException hap format error + * */ private Zip copyFileAndAlignment(File input, File tmpOutput, int alignment) throws IOException, HapFormatException { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java index 04adc9b4..37e8d1d0 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/CentralDirectory.java @@ -155,6 +155,13 @@ public class CentralDirectory { private int length; + /** + * updateLength + */ + public void updateLength() { + length = CD_LENGTH + fileNameLength + extraLength + commentLength; + } + /** * get Central Directory * @@ -199,7 +206,7 @@ public class CentralDirectory { bf.get(readComment); cd.setComment(readComment); } - cd.setLength(CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength()); + cd.updateLength(); return cd; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java new file mode 100644 index 00000000..46d44b13 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EntryType.java @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ohos.hapsigntool.zip; + +/** + * Entry Type + * + * @since 2024/06/25 + */ +public enum EntryType { + RunnableFile, + BitMap, + ResourceFile; +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index 7ab9bdc2..e1a43b20 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -19,7 +19,6 @@ import com.ohos.hapsigntool.error.CustomException; import com.ohos.hapsigntool.error.ERROR; import com.ohos.hapsigntool.error.ZipException; import com.ohos.hapsigntool.utils.FileUtils; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -43,7 +42,7 @@ public class Zip { /** * file is uncompress file flag */ - public static final int FILE_UNCOMPRESS_METHOD_FLAG = 0; + public static final short FILE_UNCOMPRESS_METHOD_FLAG = 0; /** * max comment length @@ -172,6 +171,12 @@ public class Zip { long fileSize = cd.getMethod() == FILE_UNCOMPRESS_METHOD_FLAG ? unCompressedSize : compressedSize; ZipEntryData zipEntryData = ZipEntryData.getZipEntry(file, offset, fileSize); + if (zipEntryData.getZipEntryHeader().getMethod() == FILE_UNCOMPRESS_METHOD_FLAG + && FileUtils.isRunnableFile(zipEntryData.getZipEntryHeader().getFileName())) { + zipEntryData.setType(EntryType.RunnableFile); + } else { + zipEntryData.setType(EntryType.ResourceFile); + } if (cDOffset - offset < zipEntryData.getLength()) { throw new ZipException("cd offset in front of entry end"); } @@ -189,8 +194,15 @@ public class Zip { for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), fos); - boolean isSuccess = FileUtils.appendWriteFileByOffsetToFile(file, fos, - zipEntryData.getFileOffset(), zipEntryData.getFileSize()); + boolean isSuccess; + if (entry.getZipEntryData().getType() == EntryType.BitMap) { + ByteBuffer bf = ByteBuffer.wrap(entry.getZipEntryData().getData()); + bf.order(ByteOrder.LITTLE_ENDIAN); + isSuccess = FileUtils.writeByteToOutFile(bf.array(), fos); + } else { + isSuccess = FileUtils.appendWriteFileByOffsetToFile(file, fos, + zipEntryData.getFileOffset(), zipEntryData.getFileSize()); + } if (!isSuccess) { throw new ZipException("write zip data failed"); } @@ -250,6 +262,16 @@ public class Zip { } } + public void addBitMap(byte[] data) throws ZipException { + ZipEntry entry = new ZipEntry.Builder().setMethod(FILE_UNCOMPRESS_METHOD_FLAG) + .setUncompressedSize(data.length) + .setCompressedSize(data.length) + .setFileName("pages.info") + .setData(data) + .build(); + zipEntries.add(entry); + } + /** * remove sign block */ @@ -262,22 +284,20 @@ public class Zip { * sort uncompress entry in the front. */ private void sort() { - // sort uncompress file (so, abc, an) - other uncompress file - compress file + // sort uncompress file (so, abc, an) - bitmap - other uncompress file - compress file zipEntries.sort((entry1, entry2) -> { + EntryType entry1Type = entry1.getZipEntryData().getType(); + EntryType entry2Type = entry2.getZipEntryData().getType(); + if (entry1Type != entry2Type) { + return entry1Type.compareTo(entry2Type); + } + short entry1Method = entry1.getZipEntryData().getZipEntryHeader().getMethod(); short entry2Method = entry2.getZipEntryData().getZipEntryHeader().getMethod(); String entry1FileName = entry1.getZipEntryData().getZipEntryHeader().getFileName(); String entry2FileName = entry2.getZipEntryData().getZipEntryHeader().getFileName(); if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG && entry2Method == FILE_UNCOMPRESS_METHOD_FLAG) { - boolean isRunnableFile1 = FileUtils.isRunnableFile(entry1FileName); - boolean isRunnableFile2 = FileUtils.isRunnableFile(entry2FileName); - if (isRunnableFile1 && isRunnableFile2) { - return entry1FileName.compareTo(entry2FileName); - } else if (isRunnableFile1) { - return -1; - } else if (isRunnableFile2) { - return 1; - } + return entry1FileName.compareTo(entry2FileName); } else if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG) { return -1; } else if (entry2Method == FILE_UNCOMPRESS_METHOD_FLAG) { @@ -292,6 +312,7 @@ public class Zip { long offset = 0L; long cdLength = 0L; for (ZipEntry entry : zipEntries) { + entry.updateLength(); entry.getCentralDirectory().setOffset(offset); offset += entry.getZipEntryData().getLength(); cdLength += entry.getCentralDirectory().getLength(); @@ -304,6 +325,8 @@ public class Zip { endOfCentralDirectory.setcDSize(cdLength); offset += cdLength; eOCDOffset = offset; + endOfCentralDirectory.setcDTotal(zipEntries.size()); + endOfCentralDirectory.setThisDiskCDNum(zipEntries.size()); } public List getZipEntries() { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java index ff66339a..82d7a2fb 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java @@ -18,6 +18,7 @@ package com.ohos.hapsigntool.zip; import com.ohos.hapsigntool.error.ZipException; import java.util.Arrays; +import java.util.zip.CRC32; /** * ZipEntry and CentralDirectory data @@ -27,7 +28,15 @@ import java.util.Arrays; public class ZipEntry { private ZipEntryData zipEntryData; - private CentralDirectory fileEntryIncentralDirectory; + private CentralDirectory fileEntryInCentralDirectory; + + /** + * updateLength + */ + public void updateLength() { + zipEntryData.updateLength(); + fileEntryInCentralDirectory.updateLength(); + } /** * alignment one entry @@ -40,7 +49,7 @@ public class ZipEntry { // if cd extra len bigger than entry extra len, make cd and entry extra length equals int padding = calZeroPaddingLengthForEntryExtra(); int remainder = (int) ((zipEntryData.getZipEntryHeader().getLength() - + fileEntryIncentralDirectory.getOffset()) % alignNum); + + fileEntryInCentralDirectory.getOffset()) % alignNum); if (remainder == 0) { return padding; @@ -58,7 +67,7 @@ public class ZipEntry { private int calZeroPaddingLengthForEntryExtra() throws ZipException { int entryExtraLen = zipEntryData.getZipEntryHeader().getExtraLength(); - int cdExtraLen = fileEntryIncentralDirectory.getExtraLength(); + int cdExtraLen = fileEntryInCentralDirectory.getExtraLength(); if (cdExtraLen > entryExtraLen) { setEntryHeaderNewExtraLength(cdExtraLen); return cdExtraLen - entryExtraLen; @@ -71,12 +80,12 @@ public class ZipEntry { } private void setCenterDirectoryNewExtraLength(int newLength) throws ZipException { - byte[] newCDExtra = getAlignmentNewExtra(newLength, fileEntryIncentralDirectory.getExtraData()); - fileEntryIncentralDirectory.setExtraData(newCDExtra); - fileEntryIncentralDirectory.setExtraLength(newLength); - fileEntryIncentralDirectory.setLength(CentralDirectory.CD_LENGTH - + fileEntryIncentralDirectory.getFileNameLength() - + fileEntryIncentralDirectory.getExtraLength() + fileEntryIncentralDirectory.getCommentLength()); + byte[] newCDExtra = getAlignmentNewExtra(newLength, fileEntryInCentralDirectory.getExtraData()); + fileEntryInCentralDirectory.setExtraData(newCDExtra); + fileEntryInCentralDirectory.setExtraLength(newLength); + fileEntryInCentralDirectory.setLength(CentralDirectory.CD_LENGTH + + fileEntryInCentralDirectory.getFileNameLength() + + fileEntryInCentralDirectory.getExtraLength() + fileEntryInCentralDirectory.getCommentLength()); } private void setEntryHeaderNewExtraLength(int newLength) throws ZipException { @@ -109,10 +118,143 @@ public class ZipEntry { } public CentralDirectory getCentralDirectory() { - return fileEntryIncentralDirectory; + return fileEntryInCentralDirectory; } public void setCentralDirectory(CentralDirectory centralDirectory) { - this.fileEntryIncentralDirectory = centralDirectory; + this.fileEntryInCentralDirectory = centralDirectory; + } + + public static class Builder { + private short version = 10; + + private short flag = 2048; + + private short method = 0; + + private long compressedSize; + + private long unCompressedSize; + + private String fileName; + + private byte[] extraData; + + private byte[] comment; + + private byte[] data; + + public Builder setVersion(short version) { + this.version = version; + return this; + } + + public Builder setFlag(short flag) { + this.flag = flag; + return this; + } + + public Builder setMethod(short method) { + this.method = method; + return this; + } + + public Builder setCompressedSize(long compressedSize) { + this.compressedSize = compressedSize; + return this; + } + + public Builder setUncompressedSize(long unCompressedSize) { + this.unCompressedSize = unCompressedSize; + return this; + } + + public Builder setFileName(String fileName) { + this.fileName = fileName; + return this; + } + + public Builder setExtraData(byte[] extraData) { + this.extraData = extraData; + return this; + } + + public Builder setComment(byte[] comment) { + this.comment = comment; + return this; + } + + public Builder setData(byte[] data) { + this.data = data; + return this; + } + + public ZipEntry build() throws ZipException { + ZipEntry entry = new ZipEntry(); + ZipEntryData zipEntryData = new ZipEntryData(); + zipEntryData.setData(data); + + ZipEntryHeader zipEntryHeader = new ZipEntryHeader(); + CentralDirectory cd = new CentralDirectory(); + + cd.setVersion(version); + cd.setVersionExtra(version); + zipEntryHeader.setVersion(version); + cd.setFlag(flag); + zipEntryHeader.setFlag(flag); + cd.setMethod(method); + zipEntryHeader.setMethod(method); + + cd.setLastTime((short) 0); + cd.setLastDate((short) 20001); + zipEntryHeader.setLastTime((short) 0); + zipEntryHeader.setLastDate((short) 20001); + + cd.setCompressedSize(compressedSize); + zipEntryHeader.setCompressedSize(compressedSize); + cd.setUnCompressedSize(unCompressedSize); + zipEntryHeader.setUnCompressedSize(unCompressedSize); + + cd.setFileName(fileName); + cd.setFileNameLength(fileName.length()); + zipEntryHeader.setFileName(fileName); + zipEntryHeader.setFileNameLength(fileName.length()); + + if (extraData != null) { + cd.setExtraData(extraData); + cd.setExtraLength(extraData.length); + zipEntryHeader.setExtraData(extraData); + zipEntryHeader.setExtraLength(extraData.length); + } else { + cd.setExtraLength(0); + zipEntryHeader.setExtraLength(0); + } + if (comment != null) { + cd.setComment(comment); + cd.setCommentLength(comment.length); + } else { + cd.setCommentLength(0); + } + cd.setDiskNumStart(0); + cd.setExternalFile(0); + + cd.updateLength(); + zipEntryHeader.updateLength(); + + if (data == null) { + throw new ZipException("can not find entry data"); + } + final CRC32 c = new CRC32(); + c.update(data); + final int crc32 = new Long(c.getValue()).intValue(); + cd.setCrc32(crc32); + zipEntryHeader.setCrc32(crc32); + + zipEntryData.setZipEntryHeader(zipEntryHeader); + entry.setZipEntryData(zipEntryData); + zipEntryData.setType(EntryType.BitMap); + entry.setCentralDirectory(cd); + return entry; + } } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java index 35b19e7a..4007be31 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java @@ -51,6 +51,22 @@ public class ZipEntryData { return zipEntryHeader; } + private EntryType type; + + private byte[] data; + + /** + * updateLength + */ + public void updateLength() { + zipEntryHeader.updateLength(); + if (type == EntryType.BitMap) { + length = zipEntryHeader.getLength() + data.length + (dataDescriptor == null ? 0 : 16); + } else { + length = zipEntryHeader.getLength() + fileSize + (dataDescriptor == null ? 0 : 16); + } + } + /** * init zip entry by file * @@ -140,4 +156,20 @@ public class ZipEntryData { public void setLength(long length) { this.length = length; } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public EntryType getType() { + return type; + } + + public void setType(EntryType type) { + this.type = type; + } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java index 7c880a6b..d020c8fa 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryHeader.java @@ -113,6 +113,13 @@ public class ZipEntryHeader { private int length; + /** + * updateLength + */ + public void updateLength() { + length = HEADER_LENGTH + fileNameLength + extraLength; + } + /** * get Zip Entry Header * @@ -137,7 +144,7 @@ public class ZipEntryHeader { entryHeader.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); entryHeader.setFileNameLength(UnsignedDecimalUtil.getUnsignedShort(bf)); entryHeader.setExtraLength(UnsignedDecimalUtil.getUnsignedShort(bf)); - entryHeader.setLength(HEADER_LENGTH + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); + entryHeader.updateLength(); return entryHeader; } -- Gitee From 2ae046be7f34a90dedd1f12fef306fce2aa449e1 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Thu, 4 Jul 2024 17:11:28 +0800 Subject: [PATCH 08/26] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/sign/PageInfoGenerator.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index c9b3ce21..977b9869 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -20,6 +20,7 @@ import com.ohos.hapsigntool.codesigning.elf.ElfFile; import com.ohos.hapsigntool.codesigning.elf.ElfPHeader; import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; import com.ohos.hapsigntool.entity.Pair; +import com.ohos.hapsigntool.zip.EntryType; import com.ohos.hapsigntool.zip.Zip; import com.ohos.hapsigntool.zip.ZipEntry; import com.ohos.hapsigntool.zip.ZipEntryHeader; @@ -53,9 +54,9 @@ public class PageInfoGenerator { private static final Logger LOGGER = LogManager.getLogger(PageInfoGenerator.class); - private static long maxEntryDataOffset = 0L; + private long maxEntryDataOffset = 0L; - private static final Map> libexcSegmentMap = new LinkedHashMap<>(); + private final Map> libexcSegmentMap = new LinkedHashMap<>(); /** * Constructor for PageInfoGenerator @@ -84,7 +85,9 @@ public class PageInfoGenerator { break; } maxEntryDataOffset = entryDataOffset; - libNames.put(zipEntryHeader.getFileName(), entryDataOffset); + if (EntryType.RunnableFile.equals(entry.getZipEntryData().getType())) { + libNames.put(zipEntryHeader.getFileName(), entryDataOffset); + } } File input = new File(zip.getFile()); try (JarFile hap = new JarFile(input, false)) { @@ -129,7 +132,6 @@ public class PageInfoGenerator { int end = (p.getSecond() % PAGE_SIZE_4K == 0) ? (int) ((p.getSecond() / PAGE_SIZE_4K)) * 4 : (int) ((p.getSecond() / PAGE_SIZE_4K) + 1) * 4; - // LOGGER.info(begin + " " + end); byte b = libFileName.endsWith(".abc") ? ABC_M_CODE : ELF_M_CODE; for (int i = begin; i < end; i = i + 4) { bytes[i + 3] = b; -- Gitee From b5fcdf8d5e6de699cf9e313092ea1ac797dceb68 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Mon, 15 Jul 2024 11:46:25 +0800 Subject: [PATCH 09/26] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/sign/PageInfoGenerator.java | 48 ++++++++++++++----- .../hap/provider/SignProvider.java | 13 +++-- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index 977b9869..2a245db5 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -19,7 +19,6 @@ import com.ohos.hapsigntool.codesigning.datastructure.PageInfoExtension; import com.ohos.hapsigntool.codesigning.elf.ElfFile; import com.ohos.hapsigntool.codesigning.elf.ElfPHeader; import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; -import com.ohos.hapsigntool.entity.Pair; import com.ohos.hapsigntool.zip.EntryType; import com.ohos.hapsigntool.zip.Zip; import com.ohos.hapsigntool.zip.ZipEntry; @@ -31,6 +30,7 @@ import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; @@ -56,7 +56,7 @@ public class PageInfoGenerator { private long maxEntryDataOffset = 0L; - private final Map> libexcSegmentMap = new LinkedHashMap<>(); + private final List elfExcSegmentList = new ArrayList<>(); /** * Constructor for PageInfoGenerator @@ -102,7 +102,7 @@ public class PageInfoGenerator { JarEntry libEntry = hap.getJarEntry(libFileName); if (libFileName.endsWith(".abc")) { long size = libEntry.getSize(); - libexcSegmentMap.put(libFileName, Pair.create(entryDataOffset, entryDataOffset + size)); + elfExcSegmentList.add(new ElfExcSegment(libFileName, entryDataOffset, entryDataOffset + size)); } else { try (InputStream stream = hap.getInputStream(libEntry)) { ElfFile elfFile = new ElfFile(stream); @@ -112,7 +112,7 @@ public class PageInfoGenerator { long pFilesz = programHeader.getPFilesz(); long off = entryDataOffset + pOffset; long endoff = off + pFilesz; - libexcSegmentMap.put(libFileName, Pair.create(off, endoff)); + elfExcSegmentList.add(new ElfExcSegment(libFileName, off, endoff)); } } } @@ -125,14 +125,12 @@ public class PageInfoGenerator { } int len = (int) (maxEntryDataOffset / PAGE_SIZE_1K); byte[] bytes = new byte[len]; - for (Map.Entry> e : libexcSegmentMap.entrySet()) { - String libFileName = e.getKey(); - Pair p = e.getValue(); - int begin = (int) (p.getFirst() / PAGE_SIZE_4K) * 4; - int end = (p.getSecond() % PAGE_SIZE_4K == 0) - ? (int) ((p.getSecond() / PAGE_SIZE_4K)) * 4 - : (int) ((p.getSecond() / PAGE_SIZE_4K) + 1) * 4; - byte b = libFileName.endsWith(".abc") ? ABC_M_CODE : ELF_M_CODE; + for (ElfExcSegment elf : elfExcSegmentList) { + int begin = (int) (elf.getPsStartOffset() / PAGE_SIZE_4K) * 4; + int end = (elf.getPsEndOffset() % PAGE_SIZE_4K == 0) + ? (int) ((elf.getPsEndOffset() / PAGE_SIZE_4K)) * 4 + : (int) ((elf.getPsEndOffset() / PAGE_SIZE_4K) + 1) * 4; + byte b = elf.getFileName().endsWith(".abc") ? ABC_M_CODE : ELF_M_CODE; for (int i = begin; i < end; i = i + 4) { bytes[i + 3] = b; } @@ -153,4 +151,30 @@ public class PageInfoGenerator { } return null; } + + static class ElfExcSegment { + private String fileName; + + private long psStartOffset; + + private long psEndOffset; + + ElfExcSegment(String fileName, long psStartOffset, long psEndOffset) { + this.fileName = fileName; + this.psStartOffset = psStartOffset; + this.psEndOffset = psEndOffset; + } + + public String getFileName() { + return fileName; + } + + public long getPsStartOffset() { + return psStartOffset; + } + + public long getPsEndOffset() { + return psEndOffset; + } + } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index a58fb5c9..017a9f45 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -19,6 +19,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; +import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; +import com.ohos.hapsigntool.codesigning.sign.PageInfoGenerator; import com.ohos.hapsigntool.entity.Options; import com.ohos.hapsigntool.codesigning.exception.CodeSignException; import com.ohos.hapsigntool.codesigning.exception.FsVerityDigestException; @@ -363,8 +365,9 @@ public abstract class SignProvider { outputSignedFile(outputHap, centralDirectoryOffset, signingBlock, centralDirectory, eocdBuffer); isRet = true; } - } catch (FsVerityDigestException | InvalidKeyException | HapFormatException | MissingParamsException -|InvalidParamsException |ProfileException |NumberFormatException |CustomException |IOException |CodeSignException e) { + } catch (FsVerityDigestException | InvalidKeyException | HapFormatException | MissingParamsException | + InvalidParamsException | ProfileException | NumberFormatException | CustomException | IOException | + CodeSignException | ElfFormatException e) { printErrorLogWithoutStack(e); } catch (SignatureException e) { printErrorLog(e); @@ -503,9 +506,13 @@ public abstract class SignProvider { * */ private Zip copyFileAndAlignment(File input, File tmpOutput, int alignment) - throws IOException, HapFormatException { + throws IOException, HapFormatException, ElfFormatException { Zip zip = new Zip(input); zip.alignment(alignment); + PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); + byte[] bitMap = pageInfoGenerator.generateBitMap(); + zip.addBitMap(bitMap); + zip.alignment(alignment); zip.removeSignBlock(); long start = System.currentTimeMillis(); zip.toFile(tmpOutput.getCanonicalPath()); -- Gitee From 8406ad575ea9b0ffc61eca7470ddd921bf6d1a16 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Thu, 18 Jul 2024 14:26:03 +0800 Subject: [PATCH 10/26] bitmap generator Signed-off-by: zfeixiang --- .../datastructure/PageInfoExtension.java | 2 +- .../codesigning/sign/CodeSigning.java | 2 +- .../codesigning/sign/PageInfoGenerator.java | 18 +++++++++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java index 5c0109b3..c775ada0 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -33,7 +33,7 @@ import java.nio.ByteOrder; *

* 5) u8[7] reserved: * - * @since 2023/09/08 + * @since 2024/07/01 */ public class PageInfoExtension extends Extension { /** diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index 7bc5097a..b0fbfdd5 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -211,7 +211,7 @@ public class CodeSigning { private void addPageInfoExtension(Zip zip) { long[] longs = PageInfoGenerator.getPageInfoFromZip(zip); - if (longs == null) { + if (longs.length != 2) { return; } Extension extension = new PageInfoExtension(longs[0], longs[1]); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index 2a245db5..14b3e480 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -118,6 +118,12 @@ public class PageInfoGenerator { } } + /** + * generate bitMap + * + * @return byte array of bitmap + * @throws ElfFormatException elf format error + */ public byte[] generateBitMap() throws ElfFormatException { if (maxEntryDataOffset % PAGE_SIZE_4K != 0) { throw new ElfFormatException( @@ -138,6 +144,12 @@ public class PageInfoGenerator { return bytes; } + /** + * get bitmap file's offset and size + * + * @param zip hap file + * @return long array of offset and size + */ public static long[] getPageInfoFromZip(Zip zip) { List zipEntries = zip.getZipEntries(); for (ZipEntry e : zipEntries) { @@ -145,11 +157,11 @@ public class PageInfoGenerator { if (!"pages.info".equals(fileName)) { continue; } - long fileOffset = e.getZipEntryData().getFileOffset(); - long fileSize = e.getZipEntryData().getFileSize(); + long fileOffset = e.getCentralDirectory().getOffset(); + long fileSize = e.getCentralDirectory().getUnCompressedSize(); return new long[] {fileOffset, fileSize}; } - return null; + return new long[0]; } static class ElfExcSegment { -- Gitee From c1972d167822189951608f8d478cdcf8dba5b1f4 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 20 Jul 2024 16:21:57 +0800 Subject: [PATCH 11/26] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/datastructure/Extension.java | 6 +- .../datastructure/MerkleTreeExtension.java | 5 +- .../datastructure/PageInfoExtension.java | 51 +++++++++++++--- .../codesigning/datastructure/SignInfo.java | 14 ++++- .../codesigning/elf/ElfDefine.java | 35 +++++++++++ .../hapsigntool/codesigning/elf/ElfFile.java | 6 +- .../codesigning/elf/ElfHeader.java | 4 ++ ...{ElfPHeader.java => ElfProgramHeader.java} | 4 +- .../fsverity/FsVerityDescriptor.java | 58 ++++++++++++++++--- .../fsverity/FsVerityGenerator.java | 48 +++++++++++++-- .../codesigning/sign/CodeSigning.java | 27 +++++---- .../codesigning/sign/PageInfoGenerator.java | 10 ++-- .../java/com/ohos/hapsigntool/zip/Zip.java | 3 + 13 files changed, 224 insertions(+), 47 deletions(-) rename hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/{ElfPHeader.java => ElfProgramHeader.java} (95%) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/Extension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/Extension.java index 2d23c548..6adad959 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/Extension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/Extension.java @@ -38,7 +38,7 @@ public class Extension { private final int type; - private final int size; + private int size; public Extension(int type, int size) { this.type = type; @@ -49,6 +49,10 @@ public class Extension { return EXTENSION_HEADER_SIZE; } + public void setSize(int size) { + this.size = size; + } + public boolean isType(int type) { return this.type == type; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/MerkleTreeExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/MerkleTreeExtension.java index 303d92ed..39840619 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/MerkleTreeExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/MerkleTreeExtension.java @@ -64,7 +64,7 @@ public class MerkleTreeExtension extends Extension { * @param rootHash Root hash of the merkle tree */ public MerkleTreeExtension(long merkleTreeSize, long merkleTreeOffset, byte[] rootHash) { - super(MERKLE_TREE_INLINED, MERKLE_TREE_EXTENSION_DATA_SIZE); + super(MERKLE_TREE_INLINED, Extension.EXTENSION_HEADER_SIZE + MERKLE_TREE_EXTENSION_DATA_SIZE); this.merkleTreeSize = merkleTreeSize; this.merkleTreeOffset = merkleTreeOffset; if (rootHash == null) { @@ -98,8 +98,7 @@ public class MerkleTreeExtension extends Extension { */ @Override public byte[] toByteArray() { - ByteBuffer bf = ByteBuffer.allocate(Extension.EXTENSION_HEADER_SIZE + MERKLE_TREE_EXTENSION_DATA_SIZE) - .order(ByteOrder.LITTLE_ENDIAN); + ByteBuffer bf = ByteBuffer.allocate(size()).order(ByteOrder.LITTLE_ENDIAN); bf.put(super.toByteArray()); bf.putLong(this.merkleTreeSize); bf.putLong(this.merkleTreeOffset); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java index c775ada0..47b1af25 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -31,7 +31,11 @@ import java.nio.ByteOrder; *

* 4) u8 unitSize: unit size corresponding to each page, default 4 . *

- * 5) u8[7] reserved: + * 5) u8[3] reserved: + *

+ * 6) u32 signSize: signature size + *

+ * 7) u8[] signature: signature of the data * * @since 2024/07/01 */ @@ -44,17 +48,16 @@ public class PageInfoExtension extends Extension { /** * Byte size of PageInfoExtension */ - public static final int PAGE_INFO_EXTENSION_DATA_SIZE = Extension.EXTENSION_HEADER_SIZE + 24; + public static final int PAGE_INFO_EXTENSION_DATA_SIZE_WITHOUT_SIGN = 24; /** * default unit size */ public static final int DEFAULT_UNIT_SIZE = 4; - /** - * reserved size - */ - public static final int RESERVED_SIZE = 7; + private static final int RESERVED_SIZE = 3; + + private static final int SIGNATURE_ALIGNMENT = 4; private long mapOffset; @@ -64,6 +67,12 @@ public class PageInfoExtension extends Extension { private byte[] reserved = new byte[RESERVED_SIZE]; + private int signSize; + + private byte[] signature = new byte[0]; + + private byte[] zeroPadding = new byte[0]; + /** * Constructor for PageInfoExtension * @@ -71,12 +80,32 @@ public class PageInfoExtension extends Extension { * @param mapSize bitmap size */ public PageInfoExtension(long mapOffset, long mapSize) { - super(PAGE_INFO_INLINED, PAGE_INFO_EXTENSION_DATA_SIZE); + super(PAGE_INFO_INLINED, Extension.EXTENSION_HEADER_SIZE + PAGE_INFO_EXTENSION_DATA_SIZE_WITHOUT_SIGN); this.mapOffset = mapOffset; this.mapSize = mapSize; unitSize = DEFAULT_UNIT_SIZE; } + public void setSignature(byte[] signature) { + if (signature != null) { + this.signSize = signature.length; + this.signature = signature; + this.zeroPadding = new byte[(SIGNATURE_ALIGNMENT - (signSize % SIGNATURE_ALIGNMENT)) % SIGNATURE_ALIGNMENT]; + } + super.setSize(size()); + } + + public long getMapOffset() { + return mapOffset; + } + + public long getMapSize() { + return mapSize; + } + + public byte getUnitSize() { + return unitSize; + } /** * Byte size of PageInfoExtension @@ -85,7 +114,8 @@ public class PageInfoExtension extends Extension { */ @Override public int size() { - return PAGE_INFO_EXTENSION_DATA_SIZE; + return Extension.EXTENSION_HEADER_SIZE + PAGE_INFO_EXTENSION_DATA_SIZE_WITHOUT_SIGN + signSize + + zeroPadding.length; } /** @@ -95,12 +125,15 @@ public class PageInfoExtension extends Extension { */ @Override public byte[] toByteArray() { - ByteBuffer bf = ByteBuffer.allocate(PAGE_INFO_EXTENSION_DATA_SIZE).order(ByteOrder.LITTLE_ENDIAN); + ByteBuffer bf = ByteBuffer.allocate(size()).order(ByteOrder.LITTLE_ENDIAN); bf.put(super.toByteArray()); bf.putLong(this.mapOffset); bf.putLong(this.mapSize); bf.put(this.unitSize); bf.put(this.reserved); + bf.putInt(this.signSize); + bf.put(this.signature); + bf.put(this.zeroPadding); return bf.array(); } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java index ba16f463..fb57e371 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java @@ -278,13 +278,25 @@ public class SignInfo { throw new VerifyCodeSignException("Invalid extensionType of SignInfo"); } int extensionSize = bf.getInt(); - if (extensionSize != MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE) { + if (extensionSize != (Extension.EXTENSION_HEADER_SIZE + + MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE)) { throw new VerifyCodeSignException("Invalid extensionSize of SignInfo"); } byte[] merkleTreeExtension = new byte[MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE]; bf.get(merkleTreeExtension); inExtensionList.add(MerkleTreeExtension.fromByteArray(merkleTreeExtension)); } + if (inExtensionNum >= 2) { + // parse page info extension + int extensionType = bf.getInt(); + if (extensionType != PageInfoExtension.PAGE_INFO_INLINED) { + throw new VerifyCodeSignException("Invalid extensionType of SignInfo"); + } + int extensionSize = bf.getInt(); + byte[] pageInfoExtension = new byte[extensionSize - Extension.EXTENSION_HEADER_SIZE]; + bf.get(pageInfoExtension); + // inExtensionList.add(PageInfoExtension.fromByteArray(pageInfoExtension)); + } return inExtensionList; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java index 0b19b9c0..288d5dae 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java @@ -21,13 +21,48 @@ package com.ohos.hapsigntool.codesigning.elf; * @since 2024/07/01 */ public interface ElfDefine { + /** + * 32-bit elf file + */ byte ELF_32_CLASS = 1; + + /** + * 64-bit elf file + */ byte ELF_64_CLASS = 2; + + /** + * little endian + */ byte ELF_DATA_2_LSB = 1; + + /** + * big endian + */ byte ELF_DATA_2_MSB = 2; + + /** + * 32-bit elf file's program header length + */ int ELF_PHEADER_32_LEN = 32; + + /** + * 64-bit elf file's program header length + */ int ELF_PHEADER_64_LEN = 56; + + /** + * elf header e_ident length + */ int EI_NIDENT_LEN = 16; + + /** + * 32-bit elf header length + */ int ELF_HEADER_32_LEN = EI_NIDENT_LEN + 36; + + /** + * 64-bit elf header length + */ int ELF_HEADER_64_LEN = EI_NIDENT_LEN + 48; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java index 444571a6..9fb144d4 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java @@ -31,7 +31,7 @@ import java.util.stream.Collectors; public class ElfFile { private ElfHeader elfHeader; - private List list = new ArrayList<>(); + private final List list = new ArrayList<>(); /** * Constructor for ElfFile @@ -46,7 +46,7 @@ public class ElfFile { byte eiData = elfHeader.getEiData(); short ePhnum = elfHeader.getEPhnum(); for (short i = 0; i < ePhnum; i++) { - ElfPHeader pHeader = new ElfPHeader(is, eiClass, eiData); + ElfProgramHeader pHeader = new ElfProgramHeader(is, eiClass, eiData); list.add(pHeader); } } @@ -56,7 +56,7 @@ public class ElfFile { * * @return executable program segment headers */ - public List filterExecPHeaders() { + public List filterExecPHeaders() { return list.stream().filter(phdr -> (phdr.getPFlags() & 1) == 1).collect(Collectors.toList()); } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java index 680eb7ad..b3377926 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java @@ -100,6 +100,10 @@ public class ElfHeader { is.read(bytes); ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(bo); + initHeader(byteBuffer); + } + + private void initHeader(ByteBuffer byteBuffer) throws ElfFormatException { eType = byteBuffer.getShort(); eMachine = byteBuffer.getShort(); eVersion = byteBuffer.getInt(); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfProgramHeader.java similarity index 95% rename from hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java rename to hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfProgramHeader.java index fe6447ca..8800d185 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfProgramHeader.java @@ -27,7 +27,7 @@ import java.nio.ByteOrder; * * @since 2024/07/01 */ -public class ElfPHeader { +public class ElfProgramHeader { private int pType; private int pFlags; @@ -53,7 +53,7 @@ public class ElfPHeader { * @throws IOException io error * @throws ElfFormatException elf file format error */ - public ElfPHeader(InputStream is, byte eiClass, byte eiData) throws IOException, ElfFormatException { + public ElfProgramHeader(InputStream is, byte eiClass, byte eiData) throws IOException, ElfFormatException { ByteOrder bo = ByteOrder.LITTLE_ENDIAN; if (eiData == ElfDefine.ELF_DATA_2_LSB) { bo = ByteOrder.LITTLE_ENDIAN; diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java index 5531b7f8..211233bc 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java @@ -65,6 +65,11 @@ public class FsVerityDescriptor { */ public static final byte CODE_SIGN_VERSION = 0x1; + /** + * code sign version + */ + public static final byte CODE_SIGN_VERSION_PAGE_INFO = 0x2; + /** * FsVerity descriptor size */ @@ -83,12 +88,7 @@ public class FsVerityDescriptor { /** * reserved size */ - public static final int RESERVED_SIZE_AFTER_FLAGS = 4; - - /** - * reserved size - */ - public static final int RESERVED_SIZE_AFTER_TREE_OFFSET = 127; + public static final int RESERVED_SIZE_AFTER_TREE_OFFSET = 119; private byte version; @@ -108,8 +108,12 @@ public class FsVerityDescriptor { private int flags; + private int bitMapSize; + private long merkleTreeOffset; + private long bitMapOffset; + private byte csVersion; private FsVerityDescriptor(Builder builder) { @@ -198,8 +202,9 @@ public class FsVerityDescriptor { writeBytesWithSize(buffer, rawRootHash, ROOT_HASH_FILED_SIZE); writeBytesWithSize(buffer, salt, SALT_SIZE); buffer.putInt(flags); - writeBytesWithSize(buffer, null, RESERVED_SIZE_AFTER_FLAGS); + buffer.putInt(0); buffer.putLong(merkleTreeOffset); + buffer.putLong(0); writeBytesWithSize(buffer, null, RESERVED_SIZE_AFTER_TREE_OFFSET); buffer.put(csVersion); return buffer.array(); @@ -211,7 +216,7 @@ public class FsVerityDescriptor { * @return bytes of descriptor * @throws FsVerityDigestException if error */ - public byte[] getByteForGenerateDigest() throws FsVerityDigestException { + public byte[] getDiscByte() throws FsVerityDigestException { ByteBuffer buffer = ByteBuffer.allocate(DESCRIPTOR_SIZE).order(ByteOrder.LITTLE_ENDIAN); buffer.put(CODE_SIGN_VERSION); buffer.put(hashAlgorithm); @@ -225,8 +230,39 @@ public class FsVerityDescriptor { writeBytesWithSize(buffer, rawRootHash, ROOT_HASH_FILED_SIZE); writeBytesWithSize(buffer, salt, SALT_SIZE); buffer.putInt(flags); - writeBytesWithSize(buffer, null, RESERVED_SIZE_AFTER_FLAGS); + buffer.putInt(0); + buffer.putLong(merkleTreeOffset); + return buffer.array(); + } + + /** + * Get bytes for generate digest, cs_version 2 + * + * @param mapOffset bit map data offset at file + * @param mapSize bit map size + * @param unitSize bit map unit size corresponding to each page + * @return bytes of descriptor + * @throws FsVerityDigestException if error + */ + public byte[] getDiscByteCsv2(long mapOffset, long mapSize, byte unitSize) throws FsVerityDigestException { + ByteBuffer buffer = ByteBuffer.allocate(DESCRIPTOR_SIZE).order(ByteOrder.LITTLE_ENDIAN); + buffer.put(VERSION); + buffer.put(hashAlgorithm); + buffer.put(log2BlockSize); + if (this.saltSize > SALT_SIZE) { + throw new FsVerityDigestException("Salt is too long"); + } + buffer.put(this.saltSize); + buffer.putInt(0); + buffer.putLong(fileSize); + writeBytesWithSize(buffer, rawRootHash, ROOT_HASH_FILED_SIZE); + writeBytesWithSize(buffer, salt, SALT_SIZE); + buffer.putInt((unitSize << 1 | 1)); + buffer.putInt((int) mapSize); buffer.putLong(merkleTreeOffset); + buffer.putLong(mapOffset); + writeBytesWithSize(buffer, null, RESERVED_SIZE_AFTER_TREE_OFFSET); + buffer.put(CODE_SIGN_VERSION_PAGE_INFO); return buffer.array(); } @@ -271,8 +307,12 @@ public class FsVerityDescriptor { private int flags; + private int bitMapSize; + private long merkleTreeOffset; + private long bitMapOffset; + private byte csVersion; public Builder setVersion(byte version) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityGenerator.java index 57501d09..8f0522d5 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityGenerator.java @@ -15,6 +15,7 @@ package com.ohos.hapsigntool.codesigning.fsverity; +import com.ohos.hapsigntool.codesigning.datastructure.PageInfoExtension; import com.ohos.hapsigntool.codesigning.exception.FsVerityDigestException; import com.ohos.hapsigntool.codesigning.utils.DigestUtils; @@ -42,10 +43,29 @@ public class FsVerityGenerator { private byte[] fsVerityDigest = null; + private byte[] fsVerityDigestV2 = null; + private byte[] treeBytes = null; private byte[] rootHash = null; + private PageInfoExtension pageInfoExtension; + + /** + * Constructor for FsVerityGenerator + */ + public FsVerityGenerator() { + } + + /** + * Constructor for FsVerityGenerator + * + * @param pg PageInfoExtension + */ + public FsVerityGenerator(PageInfoExtension pg) { + this.pageInfoExtension = pg; + } + /** * generate merkle tree of given input * @@ -94,14 +114,25 @@ public class FsVerityGenerator { .setRawRootHash(merkleTree.rootHash) .setFlags(flags) .setMerkleTreeOffset(fsvTreeOffset); - byte[] fsVerityDescriptor = builder.build().getByteForGenerateDigest(); - byte[] digest; try { - digest = DigestUtils.computeDigest(fsVerityDescriptor, FS_VERITY_HASH_ALGORITHM.getHashAlgorithm()); + byte[] fsVerityDescriptor = builder.build().getDiscByte(); + byte[] digest = DigestUtils.computeDigest(fsVerityDescriptor, FS_VERITY_HASH_ALGORITHM.getHashAlgorithm()); + fsVerityDigest = FsVerityDigest.getFsVerityDigest(FS_VERITY_HASH_ALGORITHM.getId(), digest); } catch (NoSuchAlgorithmException e) { throw new FsVerityDigestException("Invalid algorithm" + e.getMessage(), e); } - fsVerityDigest = FsVerityDigest.getFsVerityDigest(FS_VERITY_HASH_ALGORITHM.getId(), digest); + if (pageInfoExtension != null && fsvTreeOffset != 0) { + try { + byte[] fsVerityDescriptorV2 = builder.build() + .getDiscByteCsv2(pageInfoExtension.getMapOffset(), pageInfoExtension.getMapSize(), + pageInfoExtension.getUnitSize()); + byte[] digest = DigestUtils.computeDigest(fsVerityDescriptorV2, + FS_VERITY_HASH_ALGORITHM.getHashAlgorithm()); + fsVerityDigestV2 = FsVerityDigest.getFsVerityDigest(FS_VERITY_HASH_ALGORITHM.getId(), digest); + } catch (NoSuchAlgorithmException e) { + throw new FsVerityDigestException("Invalid algorithm" + e.getMessage(), e); + } + } treeBytes = merkleTree.tree; rootHash = merkleTree.rootHash; } @@ -115,6 +146,15 @@ public class FsVerityGenerator { return fsVerityDigest; } + /** + * Get FsVerity digest + * + * @return bytes of FsVerity digest + */ + public byte[] getFsVerityDigestV2() { + return fsVerityDigestV2; + } + /** * Get merkle tree in bytes * diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index b0fbfdd5..47b99519 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -35,6 +35,7 @@ import com.ohos.hapsigntool.error.ProfileException; import com.ohos.hapsigntool.signer.LocalSigner; import com.ohos.hapsigntool.utils.FileUtils; import com.ohos.hapsigntool.utils.StringUtils; +import com.ohos.hapsigntool.zip.EntryType; import com.ohos.hapsigntool.zip.Zip; import com.ohos.hapsigntool.zip.ZipEntry; import com.ohos.hapsigntool.zip.ZipEntryHeader; @@ -87,6 +88,7 @@ public class CodeSigning { private CodeSignBlock codeSignBlock; + private PageInfoExtension pageInfoExtension; /** * provide code sign functions to sign a hap * @@ -181,14 +183,12 @@ public class CodeSigning { LOGGER.debug("Sign hap."); String ownerID = HapUtils.getAppIdentifier(profileContent); - + createPageInfoExtension(zip); try (FileInputStream inputStream = new FileInputStream(input)) { Pair hapSignInfoAndMerkleTreeBytesPair = signFile(inputStream, dataSize, true, fsvTreeOffset, ownerID); // update hap segment in CodeSignBlock this.codeSignBlock.getHapInfoSegment().setSignInfo(hapSignInfoAndMerkleTreeBytesPair.getFirst()); - // addPageInfoExtension - addPageInfoExtension(zip); // Insert merkle tree bytes into code sign block this.codeSignBlock.addOneMerkleTree(HAP_SIGNATURE_ENTRY_NAME, hapSignInfoAndMerkleTreeBytesPair.getSecond()); @@ -209,21 +209,20 @@ public class CodeSigning { return generated; } - private void addPageInfoExtension(Zip zip) { + private void createPageInfoExtension(Zip zip) { long[] longs = PageInfoGenerator.getPageInfoFromZip(zip); - if (longs.length != 2) { - return; + if (longs.length == 2) { + pageInfoExtension = new PageInfoExtension(longs[0], longs[1]); } - Extension extension = new PageInfoExtension(longs[0], longs[1]); - this.codeSignBlock.getHapInfoSegment().getSignInfo().addExtension(extension); } private long computeDataSize(Zip zip) throws HapFormatException { long dataSize = 0L; for (ZipEntry entry : zip.getZipEntries()) { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); - if (FileUtils.isRunnableFile(zipEntryHeader.getFileName()) - && zipEntryHeader.getMethod() == Zip.FILE_UNCOMPRESS_METHOD_FLAG) { + if (EntryType.BitMap.equals(entry.getZipEntryData().getType()) || ( + FileUtils.isRunnableFile(zipEntryHeader.getFileName()) + && zipEntryHeader.getMethod() == Zip.FILE_UNCOMPRESS_METHOD_FLAG)) { continue; } // if the first file is not uncompressed abc or so, set dataSize to zero @@ -415,7 +414,7 @@ public class CodeSigning { */ public Pair signFile(InputStream inputStream, long fileSize, boolean storeTree, long fsvTreeOffset, String ownerID) throws FsVerityDigestException, CodeSignException { - FsVerityGenerator fsVerityGenerator = new FsVerityGenerator(); + FsVerityGenerator fsVerityGenerator = new FsVerityGenerator(pageInfoExtension); fsVerityGenerator.generateFsVerityDigest(inputStream, fileSize, fsvTreeOffset); byte[] fsVerityDigest = fsVerityGenerator.getFsVerityDigest(); byte[] signature = generateSignature(fsVerityDigest, ownerID); @@ -431,6 +430,12 @@ public class CodeSigning { Extension merkleTreeExtension = new MerkleTreeExtension(merkleTreeSize, fsvTreeOffset, fsVerityGenerator.getRootHash()); signInfo.addExtension(merkleTreeExtension); + if (pageInfoExtension != null) { + byte[] fsVerityDigestV2 = fsVerityGenerator.getFsVerityDigestV2(); + byte[] signatureV2 = generateSignature(fsVerityDigestV2, ownerID); + pageInfoExtension.setSignature(signatureV2); + signInfo.addExtension(pageInfoExtension); + } } return Pair.create(signInfo, fsVerityGenerator.getTreeBytes()); } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index 14b3e480..45e6664c 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -17,7 +17,7 @@ package com.ohos.hapsigntool.codesigning.sign; import com.ohos.hapsigntool.codesigning.datastructure.PageInfoExtension; import com.ohos.hapsigntool.codesigning.elf.ElfFile; -import com.ohos.hapsigntool.codesigning.elf.ElfPHeader; +import com.ohos.hapsigntool.codesigning.elf.ElfProgramHeader; import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; import com.ohos.hapsigntool.zip.EntryType; import com.ohos.hapsigntool.zip.Zip; @@ -106,8 +106,8 @@ public class PageInfoGenerator { } else { try (InputStream stream = hap.getInputStream(libEntry)) { ElfFile elfFile = new ElfFile(stream); - List elfPHeaders = elfFile.filterExecPHeaders(); - for (ElfPHeader programHeader : elfPHeaders) { + List elfPHeaders = elfFile.filterExecPHeaders(); + for (ElfProgramHeader programHeader : elfPHeaders) { long pOffset = programHeader.getPOffset(); long pFilesz = programHeader.getPFilesz(); long off = entryDataOffset + pOffset; @@ -157,7 +157,9 @@ public class PageInfoGenerator { if (!"pages.info".equals(fileName)) { continue; } - long fileOffset = e.getCentralDirectory().getOffset(); + long fileOffset = e.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + e.getZipEntryData() + .getZipEntryHeader() + .getFileNameLength() + e.getZipEntryData().getZipEntryHeader().getExtraLength(); long fileSize = e.getCentralDirectory().getUnCompressedSize(); return new long[] {fileOffset, fileSize}; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index e1a43b20..9623b007 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -244,6 +244,9 @@ public class Zip { zipEntryData.getZipEntryHeader().getFileName())) { // .abc and .so file align 4096 byte. alignBytes = 4096; + } else if (EntryType.BitMap.equals(entry.getZipEntryData().getType()) ) { + // bitmap file + alignBytes = 4096; } else if (isFirstUnRunnableFile) { // the first file after runnable file, align 4096 byte. alignBytes = 4096; -- Gitee From 5d2faf33203946f142de0febd6b845e76a993a0c Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 20 Jul 2024 19:16:19 +0800 Subject: [PATCH 12/26] bitmap generator Signed-off-by: zfeixiang --- .../ohos/hapsigntool/codesigning/sign/CodeSigning.java | 1 + .../hapsigntool/codesigning/sign/PageInfoGenerator.java | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index 47b99519..b4ea8f49 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -89,6 +89,7 @@ public class CodeSigning { private CodeSignBlock codeSignBlock; private PageInfoExtension pageInfoExtension; + /** * provide code sign functions to sign a hap * diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index 45e6664c..7b0b5dc9 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -19,6 +19,7 @@ import com.ohos.hapsigntool.codesigning.datastructure.PageInfoExtension; import com.ohos.hapsigntool.codesigning.elf.ElfFile; import com.ohos.hapsigntool.codesigning.elf.ElfProgramHeader; import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; +import com.ohos.hapsigntool.error.HapFormatException; import com.ohos.hapsigntool.zip.EntryType; import com.ohos.hapsigntool.zip.Zip; import com.ohos.hapsigntool.zip.ZipEntry; @@ -61,6 +62,7 @@ public class PageInfoGenerator { /** * Constructor for PageInfoGenerator * + * @param input file * @throws IOException io error * @throws ElfFormatException elf file format error */ @@ -71,6 +73,7 @@ public class PageInfoGenerator { /** * Constructor for PageInfoGenerator * + * @param zip zip * @throws IOException io error * @throws ElfFormatException elf file format error */ @@ -122,11 +125,11 @@ public class PageInfoGenerator { * generate bitMap * * @return byte array of bitmap - * @throws ElfFormatException elf format error + * @throws HapFormatException hap format error */ - public byte[] generateBitMap() throws ElfFormatException { + public byte[] generateBitMap() throws HapFormatException { if (maxEntryDataOffset % PAGE_SIZE_4K != 0) { - throw new ElfFormatException( + throw new HapFormatException( String.format(Locale.ROOT, "Invalid maxEndOff(%d), not a multiple of 4096", maxEntryDataOffset)); } int len = (int) (maxEntryDataOffset / PAGE_SIZE_1K); -- Gitee From 4a0ce488c44cc51586615296241885f22b9fb4a1 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 20 Jul 2024 19:35:48 +0800 Subject: [PATCH 13/26] bitmap generator Signed-off-by: zfeixiang --- .../datastructure/PageInfoExtension.java | 31 +++++++++++++++++++ .../codesigning/datastructure/SignInfo.java | 2 +- .../codesigning/sign/CodeSigning.java | 2 +- 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java index 47b1af25..b386da3b 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -15,6 +15,8 @@ package com.ohos.hapsigntool.codesigning.datastructure; +import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; + import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -136,4 +138,33 @@ public class PageInfoExtension extends Extension { bf.put(this.zeroPadding); return bf.array(); } + + /** + * Init the PageInfoExtension by a byte array + * + * @param bytes Byte array representation of a PageInfoExtension object + * @return a newly created PageInfoExtension object + */ + public static PageInfoExtension fromByteArray(byte[] bytes) throws VerifyCodeSignException { + ByteBuffer bf = ByteBuffer.allocate(bytes.length).order(ByteOrder.LITTLE_ENDIAN); + bf.put(bytes); + bf.rewind(); + long mapOffset = bf.getLong(); + if (mapOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { + throw new VerifyCodeSignException("mapOffset is not a multiple of 4096"); + } + long mapSize = bf.getLong(); + byte unitSize = bf.get(); + if (mapSize % unitSize != 0) { + throw new VerifyCodeSignException("mapSize is not a multiple of unitSize"); + } + bf.get(new byte[RESERVED_SIZE]); + int signSize = bf.getInt(); + byte[] signature = new byte[signSize]; + bf.get(signature); + PageInfoExtension extension = new PageInfoExtension(mapOffset, mapSize); + extension.unitSize = unitSize; + extension.setSignature(signature); + return extension; + } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java index fb57e371..ca5666b8 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java @@ -295,7 +295,7 @@ public class SignInfo { int extensionSize = bf.getInt(); byte[] pageInfoExtension = new byte[extensionSize - Extension.EXTENSION_HEADER_SIZE]; bf.get(pageInfoExtension); - // inExtensionList.add(PageInfoExtension.fromByteArray(pageInfoExtension)); + inExtensionList.add(PageInfoExtension.fromByteArray(pageInfoExtension)); } return inExtensionList; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index b4ea8f49..61944703 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -89,7 +89,7 @@ public class CodeSigning { private CodeSignBlock codeSignBlock; private PageInfoExtension pageInfoExtension; - + /** * provide code sign functions to sign a hap * -- Gitee From 79c14fdfd2003adf81aa6ea3a41a97d033da30b4 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Mon, 22 Jul 2024 10:19:45 +0800 Subject: [PATCH 14/26] only hap sign bitmap Signed-off-by: wangzeyu --- .../hapsigntool/hap/provider/SignProvider.java | 14 ++++++++------ .../main/java/com/ohos/hapsigntool/zip/Zip.java | 15 +++++++++------ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index 017a9f45..5133c73d 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -338,7 +338,7 @@ public abstract class SignProvider { } // copy file and Alignment int alignment = Integer.parseInt(signParams.get(ParamConstants.PARAM_BASIC_ALIGNMENT)); - Zip zip = copyFileAndAlignment(input, tmpOutput, alignment); + Zip zip = copyFileAndAlignment(input, tmpOutput, alignment, suffix); // generate sign block and output signedHap try (RandomAccessFile outputHap = new RandomAccessFile(tmpOutput, "rw")) { ZipDataInput outputHapIn = new RandomAccessFileZipDataInput(outputHap); @@ -505,14 +505,16 @@ public abstract class SignProvider { * @throws HapFormatException hap format error * */ - private Zip copyFileAndAlignment(File input, File tmpOutput, int alignment) + private Zip copyFileAndAlignment(File input, File tmpOutput, int alignment, String suffix) throws IOException, HapFormatException, ElfFormatException { Zip zip = new Zip(input); zip.alignment(alignment); - PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); - byte[] bitMap = pageInfoGenerator.generateBitMap(); - zip.addBitMap(bitMap); - zip.alignment(alignment); + if (suffix.equals("hap")) { + PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); + byte[] bitMap = pageInfoGenerator.generateBitMap(); + zip.addBitMap(bitMap); + zip.alignment(alignment); + } zip.removeSignBlock(); long start = System.currentTimeMillis(); zip.toFile(tmpOutput.getCanonicalPath()); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index 9623b007..64fb328e 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -63,6 +63,9 @@ public class Zip { private String file; + private final String bitMapFilename = "pages.info"; + + /** * create Zip by file * @@ -174,6 +177,9 @@ public class Zip { if (zipEntryData.getZipEntryHeader().getMethod() == FILE_UNCOMPRESS_METHOD_FLAG && FileUtils.isRunnableFile(zipEntryData.getZipEntryHeader().getFileName())) { zipEntryData.setType(EntryType.RunnableFile); + } else if (zipEntryData.getZipEntryHeader().getFileName().equals(bitMapFilename)) { + // skip bitmap + continue; } else { zipEntryData.setType(EntryType.ResourceFile); } @@ -240,13 +246,10 @@ public class Zip { break; } int alignBytes; - if (method == FILE_UNCOMPRESS_METHOD_FLAG && FileUtils.isRunnableFile( - zipEntryData.getZipEntryHeader().getFileName())) { + EntryType type = entry.getZipEntryData().getType(); + if (type == EntryType.RunnableFile || type == EntryType.BitMap) { // .abc and .so file align 4096 byte. alignBytes = 4096; - } else if (EntryType.BitMap.equals(entry.getZipEntryData().getType()) ) { - // bitmap file - alignBytes = 4096; } else if (isFirstUnRunnableFile) { // the first file after runnable file, align 4096 byte. alignBytes = 4096; @@ -269,7 +272,7 @@ public class Zip { ZipEntry entry = new ZipEntry.Builder().setMethod(FILE_UNCOMPRESS_METHOD_FLAG) .setUncompressedSize(data.length) .setCompressedSize(data.length) - .setFileName("pages.info") + .setFileName(bitMapFilename) .setData(data) .build(); zipEntries.add(entry); -- Gitee From f24518abb0251beff6affdce7e9d39c7ab6fe4ad Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Mon, 22 Jul 2024 10:21:28 +0800 Subject: [PATCH 15/26] only hap sign bitmap Signed-off-by: wangzeyu --- .../codesigning/elf/ElfPHeader.java | 105 ++++++++++++++++++ .../hap/provider/SignProvider.java | 6 +- 2 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java new file mode 100644 index 00000000..fe6447ca --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.codesigning.elf; + +import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +/** + * ELF program header info + * + * @since 2024/07/01 + */ +public class ElfPHeader { + private int pType; + + private int pFlags; + + private long pOffset; + + private long pVaddr; + + private long pPaddr; + + private long pFilesz; + + private long pMemsz; + + private long pAlign; + + /** + * Constructor for ElfPHeader + * + * @param is InputStream + * @param eiClass eiClass + * @param eiData eiData + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ + public ElfPHeader(InputStream is, byte eiClass, byte eiData) throws IOException, ElfFormatException { + ByteOrder bo = ByteOrder.LITTLE_ENDIAN; + if (eiData == ElfDefine.ELF_DATA_2_LSB) { + bo = ByteOrder.LITTLE_ENDIAN; + } else if (eiData == ElfDefine.ELF_DATA_2_MSB) { + bo = ByteOrder.BIG_ENDIAN; + } else { + throw new ElfFormatException("ELF ei_data is incorrect"); + } + if (eiClass == ElfDefine.ELF_32_CLASS) { + byte[] bytes = new byte[ElfDefine.ELF_PHEADER_32_LEN]; + is.read(bytes); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + byteBuffer.order(bo); + pType = byteBuffer.getInt(); + pOffset = byteBuffer.getInt() & 0xFFFFFFFFL; + pVaddr = byteBuffer.getInt() & 0xFFFFFFFFL; + pPaddr = byteBuffer.getInt() & 0xFFFFFFFFL; + pFilesz = byteBuffer.getInt(); + pMemsz = byteBuffer.getInt(); + pFlags = byteBuffer.getInt(); + pAlign = byteBuffer.getInt(); + } else { + byte[] bytes = new byte[ElfDefine.ELF_PHEADER_64_LEN]; + is.read(bytes); + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + byteBuffer.order(bo); + pType = byteBuffer.getInt(); + pFlags = byteBuffer.getInt(); + pOffset = byteBuffer.getLong(); + pVaddr = byteBuffer.getLong(); + pPaddr = byteBuffer.getLong(); + pFilesz = byteBuffer.getLong(); + pMemsz = byteBuffer.getLong(); + pAlign = byteBuffer.getLong(); + } + } + + public int getPFlags() { + return pFlags; + } + + public long getPOffset() { + return pOffset; + } + + public long getPFilesz() { + return pFilesz; + } +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index 5133c73d..b27202dc 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -512,8 +512,10 @@ public abstract class SignProvider { if (suffix.equals("hap")) { PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); byte[] bitMap = pageInfoGenerator.generateBitMap(); - zip.addBitMap(bitMap); - zip.alignment(alignment); + if (bitMap != null) { + zip.addBitMap(bitMap); + zip.alignment(alignment); + } } zip.removeSignBlock(); long start = System.currentTimeMillis(); -- Gitee From d0508387d829a67b2a7c316fe34901b7c2d6d6d9 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Mon, 22 Jul 2024 10:22:14 +0800 Subject: [PATCH 16/26] only hap sign bitmap Signed-off-by: wangzeyu --- .../codesigning/elf/ElfPHeader.java | 105 ------------------ 1 file changed, 105 deletions(-) delete mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java deleted file mode 100644 index fe6447ca..00000000 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfPHeader.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2024-2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.ohos.hapsigntool.codesigning.elf; - -import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - -/** - * ELF program header info - * - * @since 2024/07/01 - */ -public class ElfPHeader { - private int pType; - - private int pFlags; - - private long pOffset; - - private long pVaddr; - - private long pPaddr; - - private long pFilesz; - - private long pMemsz; - - private long pAlign; - - /** - * Constructor for ElfPHeader - * - * @param is InputStream - * @param eiClass eiClass - * @param eiData eiData - * @throws IOException io error - * @throws ElfFormatException elf file format error - */ - public ElfPHeader(InputStream is, byte eiClass, byte eiData) throws IOException, ElfFormatException { - ByteOrder bo = ByteOrder.LITTLE_ENDIAN; - if (eiData == ElfDefine.ELF_DATA_2_LSB) { - bo = ByteOrder.LITTLE_ENDIAN; - } else if (eiData == ElfDefine.ELF_DATA_2_MSB) { - bo = ByteOrder.BIG_ENDIAN; - } else { - throw new ElfFormatException("ELF ei_data is incorrect"); - } - if (eiClass == ElfDefine.ELF_32_CLASS) { - byte[] bytes = new byte[ElfDefine.ELF_PHEADER_32_LEN]; - is.read(bytes); - ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - byteBuffer.order(bo); - pType = byteBuffer.getInt(); - pOffset = byteBuffer.getInt() & 0xFFFFFFFFL; - pVaddr = byteBuffer.getInt() & 0xFFFFFFFFL; - pPaddr = byteBuffer.getInt() & 0xFFFFFFFFL; - pFilesz = byteBuffer.getInt(); - pMemsz = byteBuffer.getInt(); - pFlags = byteBuffer.getInt(); - pAlign = byteBuffer.getInt(); - } else { - byte[] bytes = new byte[ElfDefine.ELF_PHEADER_64_LEN]; - is.read(bytes); - ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); - byteBuffer.order(bo); - pType = byteBuffer.getInt(); - pFlags = byteBuffer.getInt(); - pOffset = byteBuffer.getLong(); - pVaddr = byteBuffer.getLong(); - pPaddr = byteBuffer.getLong(); - pFilesz = byteBuffer.getLong(); - pMemsz = byteBuffer.getLong(); - pAlign = byteBuffer.getLong(); - } - } - - public int getPFlags() { - return pFlags; - } - - public long getPOffset() { - return pOffset; - } - - public long getPFilesz() { - return pFilesz; - } -} -- Gitee From 6ce6201b89792abd5c6c2d48ae6453e2624e55ea Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Tue, 23 Jul 2024 15:42:47 +0800 Subject: [PATCH 17/26] bitmap generator Signed-off-by: zfeixiang --- .../datastructure/PageInfoExtension.java | 19 ++++++++++--------- .../fsverity/FsVerityDescriptor.java | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java index b386da3b..4bb4ba94 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -144,27 +144,28 @@ public class PageInfoExtension extends Extension { * * @param bytes Byte array representation of a PageInfoExtension object * @return a newly created PageInfoExtension object + * @throws VerifyCodeSignException parse result invalid */ public static PageInfoExtension fromByteArray(byte[] bytes) throws VerifyCodeSignException { ByteBuffer bf = ByteBuffer.allocate(bytes.length).order(ByteOrder.LITTLE_ENDIAN); bf.put(bytes); bf.rewind(); - long mapOffset = bf.getLong(); - if (mapOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { + long inMapOffset = bf.getLong(); + if (inMapOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { throw new VerifyCodeSignException("mapOffset is not a multiple of 4096"); } - long mapSize = bf.getLong(); + long inMapSize = bf.getLong(); byte unitSize = bf.get(); - if (mapSize % unitSize != 0) { + if (inMapSize % unitSize != 0) { throw new VerifyCodeSignException("mapSize is not a multiple of unitSize"); } bf.get(new byte[RESERVED_SIZE]); - int signSize = bf.getInt(); - byte[] signature = new byte[signSize]; - bf.get(signature); - PageInfoExtension extension = new PageInfoExtension(mapOffset, mapSize); + int inSignSize = bf.getInt(); + byte[] inSignature = new byte[inSignSize]; + bf.get(inSignature); + PageInfoExtension extension = new PageInfoExtension(inMapOffset, inMapSize); extension.unitSize = unitSize; - extension.setSignature(signature); + extension.setSignature(inSignature); return extension; } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java index 211233bc..8acc2081 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java @@ -156,7 +156,7 @@ public class FsVerityDescriptor { bf.rewind(); FsVerityDescriptor.Builder builder = new FsVerityDescriptor.Builder(); byte inFsVersion = bf.get(); - if (FsVerityDescriptor.VERSION != inFsVersion) { + if (inFsVersion != FsVerityDescriptor.VERSION) { throw new VerifyCodeSignException("Invalid fs-verify descriptor version of ElfSignBlock"); } byte inFsHashAlgorithm = bf.get(); -- Gitee From 11aad050e9cb098bd061fcc1fb9c711df00f7116 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Tue, 23 Jul 2024 16:21:44 +0800 Subject: [PATCH 18/26] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/sign/CodeSigning.java | 6 +----- .../codesigning/sign/PageInfoGenerator.java | 7 ++++--- .../com/ohos/hapsigntool/utils/FileUtils.java | 17 ++++++++++++++++- .../main/java/com/ohos/hapsigntool/zip/Zip.java | 6 ++---- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index 61944703..236551f7 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -80,10 +80,6 @@ public class CodeSigning { private static final Logger LOGGER = LogManager.getLogger(CodeSigning.class); - private static final String NATIVE_LIB_AN_SUFFIX = ".an"; - - private static final String NATIVE_LIB_SO_SUFFIX = ".so"; - private final SignerConfig signConfig; private CodeSignBlock codeSignBlock; @@ -356,7 +352,7 @@ public class CodeSigning { if (StringUtils.isEmpty(entryName)) { return false; } - if (entryName.endsWith(NATIVE_LIB_AN_SUFFIX)) { + if (entryName.endsWith(FileUtils.NATIVE_LIB_AN_SUFFIX)) { return true; } if (entryName.startsWith(FileUtils.LIBS_PATH_PREFIX)) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index 7b0b5dc9..277eb00d 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -20,6 +20,7 @@ import com.ohos.hapsigntool.codesigning.elf.ElfFile; import com.ohos.hapsigntool.codesigning.elf.ElfProgramHeader; import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; import com.ohos.hapsigntool.error.HapFormatException; +import com.ohos.hapsigntool.utils.FileUtils; import com.ohos.hapsigntool.zip.EntryType; import com.ohos.hapsigntool.zip.Zip; import com.ohos.hapsigntool.zip.ZipEntry; @@ -103,7 +104,7 @@ public class PageInfoGenerator { private void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) throws IOException, ElfFormatException { JarEntry libEntry = hap.getJarEntry(libFileName); - if (libFileName.endsWith(".abc")) { + if (libFileName.endsWith(FileUtils.ABC_FILE_SUFFIX)) { long size = libEntry.getSize(); elfExcSegmentList.add(new ElfExcSegment(libFileName, entryDataOffset, entryDataOffset + size)); } else { @@ -139,7 +140,7 @@ public class PageInfoGenerator { int end = (elf.getPsEndOffset() % PAGE_SIZE_4K == 0) ? (int) ((elf.getPsEndOffset() / PAGE_SIZE_4K)) * 4 : (int) ((elf.getPsEndOffset() / PAGE_SIZE_4K) + 1) * 4; - byte b = elf.getFileName().endsWith(".abc") ? ABC_M_CODE : ELF_M_CODE; + byte b = elf.getFileName().endsWith(FileUtils.ABC_FILE_SUFFIX) ? ABC_M_CODE : ELF_M_CODE; for (int i = begin; i < end; i = i + 4) { bytes[i + 3] = b; } @@ -157,7 +158,7 @@ public class PageInfoGenerator { List zipEntries = zip.getZipEntries(); for (ZipEntry e : zipEntries) { String fileName = e.getCentralDirectory().getFileName(); - if (!"pages.info".equals(fileName)) { + if (!FileUtils.BIT_MAP_FILENAME.equals(fileName)) { continue; } long fileOffset = e.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + e.getZipEntryData() diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java index 72301e87..fe65899a 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java @@ -78,6 +78,21 @@ public final class FileUtils { */ public static final String LIBS_PATH_PREFIX = "libs/"; + /** + * abc file suffix + */ + public static final String ABC_FILE_SUFFIX = ".abc"; + + /** + * an file suffix + */ + public static final String NATIVE_LIB_AN_SUFFIX = ".an"; + + /** + * bitmap file name + */ + public static final String BIT_MAP_FILENAME = ".pages.info"; + private static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; private FileUtils() { @@ -494,7 +509,7 @@ public final class FileUtils { if (StringUtils.isEmpty(name)) { return false; } - if (name.endsWith(".an") || name.endsWith(".abc")) { + if (name.endsWith(NATIVE_LIB_AN_SUFFIX) || name.endsWith(ABC_FILE_SUFFIX)) { return true; } if (name.startsWith(LIBS_PATH_PREFIX)) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index 64fb328e..6f7ed37f 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -63,8 +63,6 @@ public class Zip { private String file; - private final String bitMapFilename = "pages.info"; - /** * create Zip by file @@ -177,7 +175,7 @@ public class Zip { if (zipEntryData.getZipEntryHeader().getMethod() == FILE_UNCOMPRESS_METHOD_FLAG && FileUtils.isRunnableFile(zipEntryData.getZipEntryHeader().getFileName())) { zipEntryData.setType(EntryType.RunnableFile); - } else if (zipEntryData.getZipEntryHeader().getFileName().equals(bitMapFilename)) { + } else if (zipEntryData.getZipEntryHeader().getFileName().equals(FileUtils.BIT_MAP_FILENAME)) { // skip bitmap continue; } else { @@ -272,7 +270,7 @@ public class Zip { ZipEntry entry = new ZipEntry.Builder().setMethod(FILE_UNCOMPRESS_METHOD_FLAG) .setUncompressedSize(data.length) .setCompressedSize(data.length) - .setFileName(bitMapFilename) + .setFileName(FileUtils.BIT_MAP_FILENAME) .setData(data) .build(); zipEntries.add(entry); -- Gitee From e8daba9ed0663e736c9c88bf4f03e9e1e60b7f41 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 23 Jul 2024 17:15:36 +0800 Subject: [PATCH 19/26] =?UTF-8?q?only=20hap=20sign=20bitmap=EF=BC=8C=20rep?= =?UTF-8?q?air=20sort=20null=20pointer=20exception?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: wangzeyu --- .../main/java/com/ohos/hapsigntool/zip/Zip.java | 15 ++++++--------- .../com/ohos/hapsigntool/zip/ZipEntryData.java | 12 +++++++++++- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index 6f7ed37f..3b016a68 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -172,15 +172,6 @@ public class Zip { long fileSize = cd.getMethod() == FILE_UNCOMPRESS_METHOD_FLAG ? unCompressedSize : compressedSize; ZipEntryData zipEntryData = ZipEntryData.getZipEntry(file, offset, fileSize); - if (zipEntryData.getZipEntryHeader().getMethod() == FILE_UNCOMPRESS_METHOD_FLAG - && FileUtils.isRunnableFile(zipEntryData.getZipEntryHeader().getFileName())) { - zipEntryData.setType(EntryType.RunnableFile); - } else if (zipEntryData.getZipEntryHeader().getFileName().equals(FileUtils.BIT_MAP_FILENAME)) { - // skip bitmap - continue; - } else { - zipEntryData.setType(EntryType.ResourceFile); - } if (cDOffset - offset < zipEntryData.getLength()) { throw new ZipException("cd offset in front of entry end"); } @@ -267,6 +258,12 @@ public class Zip { } public void addBitMap(byte[] data) throws ZipException { + for (ZipEntry e : zipEntries) { + if (e.getZipEntryData().getType() == EntryType.BitMap) { + e.getZipEntryData().setData(data); + return; + } + } ZipEntry entry = new ZipEntry.Builder().setMethod(FILE_UNCOMPRESS_METHOD_FLAG) .setUncompressedSize(data.length) .setCompressedSize(data.length) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java index 4007be31..fc9327cb 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java @@ -102,7 +102,17 @@ public class ZipEntryData { ZipEntryData entry = new ZipEntryData(); entry.setFileOffset(offset); entry.setFileSize(fileSize); - input.skip(fileSize); + byte[] data = FileUtils.readInputByLength(input, fileSize); + + if (entryHeader.getMethod() == Zip.FILE_UNCOMPRESS_METHOD_FLAG + && FileUtils.isRunnableFile(entryHeader.getFileName())) { + entry.setType(EntryType.RunnableFile); + } else if (entryHeader.getFileName().equals(FileUtils.BIT_MAP_FILENAME)) { + entry.setType(EntryType.BitMap); + entry.data = data; + } else { + entry.setType(EntryType.ResourceFile); + } long entryLength = entryHeader.getLength() + fileSize; short flag = entryHeader.getFlag(); -- Gitee From 1d4e713d8e38941de4c9f319a734fe949ee40032 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Tue, 23 Jul 2024 19:53:48 +0800 Subject: [PATCH 20/26] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/datastructure/PageInfoExtension.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java index 4bb4ba94..170733fc 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -155,8 +155,8 @@ public class PageInfoExtension extends Extension { throw new VerifyCodeSignException("mapOffset is not a multiple of 4096"); } long inMapSize = bf.getLong(); - byte unitSize = bf.get(); - if (inMapSize % unitSize != 0) { + byte inUnitSize = bf.get(); + if (inMapSize % inUnitSize != 0) { throw new VerifyCodeSignException("mapSize is not a multiple of unitSize"); } bf.get(new byte[RESERVED_SIZE]); @@ -164,7 +164,7 @@ public class PageInfoExtension extends Extension { byte[] inSignature = new byte[inSignSize]; bf.get(inSignature); PageInfoExtension extension = new PageInfoExtension(inMapOffset, inMapSize); - extension.unitSize = unitSize; + extension.unitSize = inUnitSize; extension.setSignature(inSignature); return extension; } -- Gitee From d7cc0b01c391f0c181d02e83659cfec810c37817 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Tue, 23 Jul 2024 20:56:31 +0800 Subject: [PATCH 21/26] change name Signed-off-by: zfeixiang --- .../com/ohos/hapsigntool/codesigning/sign/CodeSigning.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index 236551f7..eb1f8d9e 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -207,9 +207,9 @@ public class CodeSigning { } private void createPageInfoExtension(Zip zip) { - long[] longs = PageInfoGenerator.getPageInfoFromZip(zip); - if (longs.length == 2) { - pageInfoExtension = new PageInfoExtension(longs[0], longs[1]); + long[] bitmapOffSize = PageInfoGenerator.getPageInfoFromZip(zip); + if (bitmapOffSize.length == 2) { + pageInfoExtension = new PageInfoExtension(bitmapOffSize[0], bitmapOffSize[1]); } } -- Gitee From e58dde452c66e56cee42c07e948358ffeed8daaa Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Wed, 24 Jul 2024 09:47:17 +0800 Subject: [PATCH 22/26] bitmap generator Signed-off-by: zfeixiang --- .../datastructure/PageInfoExtension.java | 6 +++--- .../codesigning/sign/PageInfoGenerator.java | 14 ++++++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java index 170733fc..4dae86b5 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -27,9 +27,9 @@ import java.nio.ByteOrder; *

* 1) u32 type 0x2 *

- * 2) u64 mapOffset: the size of bitmap + * 2) u64 mapOffset: offset of the bitmap by the start of the file. *

- * 3) u64 mapSize: offset of the bitmap by the start of the file. + * 3) u64 mapSize: the bit size of bitmap. *

* 4) u8 unitSize: unit size corresponding to each page, default 4 . *

@@ -79,7 +79,7 @@ public class PageInfoExtension extends Extension { * Constructor for PageInfoExtension * * @param mapOffset bitmap offset - * @param mapSize bitmap size + * @param mapSize bit size */ public PageInfoExtension(long mapOffset, long mapSize) { super(PAGE_INFO_INLINED, Extension.EXTENSION_HEADER_SIZE + PAGE_INFO_EXTENSION_DATA_SIZE_WITHOUT_SIGN); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index 277eb00d..ff0fc727 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -33,6 +33,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.BitSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; @@ -134,7 +135,7 @@ public class PageInfoGenerator { String.format(Locale.ROOT, "Invalid maxEndOff(%d), not a multiple of 4096", maxEntryDataOffset)); } int len = (int) (maxEntryDataOffset / PAGE_SIZE_1K); - byte[] bytes = new byte[len]; + BitSet bitmap = new BitSet(len); for (ElfExcSegment elf : elfExcSegmentList) { int begin = (int) (elf.getPsStartOffset() / PAGE_SIZE_4K) * 4; int end = (elf.getPsEndOffset() % PAGE_SIZE_4K == 0) @@ -142,10 +143,14 @@ public class PageInfoGenerator { : (int) ((elf.getPsEndOffset() / PAGE_SIZE_4K) + 1) * 4; byte b = elf.getFileName().endsWith(FileUtils.ABC_FILE_SUFFIX) ? ABC_M_CODE : ELF_M_CODE; for (int i = begin; i < end; i = i + 4) { - bytes[i + 3] = b; + if ((ELF_M_CODE == b)) { + bitmap.set(i + 3); + } else { + bitmap.set(i + 2); + } } } - return bytes; + return bitmap.toByteArray(); } /** @@ -165,7 +170,8 @@ public class PageInfoGenerator { .getZipEntryHeader() .getFileNameLength() + e.getZipEntryData().getZipEntryHeader().getExtraLength(); long fileSize = e.getCentralDirectory().getUnCompressedSize(); - return new long[] {fileOffset, fileSize}; + long bitmapSize = fileSize * 8; + return new long[] {fileOffset, bitmapSize}; } return new long[0]; } -- Gitee From dfd9c40a57f987b30f2d5af7a82591ccbe1c8bf4 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Wed, 24 Jul 2024 22:20:34 +0800 Subject: [PATCH 23/26] code check Signed-off-by: zfeixiang --- .../codesigning/datastructure/SignInfo.java | 49 +++++++-------- .../hapsigntool/codesigning/elf/ElfFile.java | 12 +++- .../codesigning/elf/ElfHeader.java | 59 +++++++++++++++--- .../codesigning/elf/ElfProgramHeader.java | 34 +++++++++- .../fsverity/FsVerityDescriptor.java | 6 +- .../fsverity/FsVerityGenerator.java | 2 +- .../codesigning/sign/CodeSigning.java | 5 +- .../codesigning/sign/PageInfoGenerator.java | 62 ++++++++++++------- 8 files changed, 161 insertions(+), 68 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java index ca5666b8..d146bf8f 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/SignInfo.java @@ -112,6 +112,7 @@ public class SignInfo { this.sigSize = sig == null ? 0 : sig.length; // align for extension after signature this.zeroPadding = new byte[(SIGNATURE_ALIGNMENT - (this.sigSize % SIGNATURE_ALIGNMENT)) % SIGNATURE_ALIGNMENT]; + this.extensionOffset = SIGN_INFO_SIZE_WITHOUT_SIGNATURE + sigSize + this.zeroPadding.length; } /** @@ -138,7 +139,6 @@ public class SignInfo { * @param extension Extension object */ public void addExtension(Extension extension) { - this.extensionOffset = SIGN_INFO_SIZE_WITHOUT_SIGNATURE + this.signature.length + this.zeroPadding.length; this.extensionList.add(extension); this.extensionNum = this.extensionList.size(); } @@ -254,7 +254,7 @@ public class SignInfo { % SIGNATURE_ALIGNMENT]; bf.get(inZeroPadding); // parse merkle tree extension - List inExtensionList = parseMerkleTreeExtension(bf, inExtensionNum); + List inExtensionList = parseExtensionList(bf, inExtensionNum); return new SignInfoBuilder().setSaltSize(inSaltSize) .setSigSize(inSigSize) .setFlags(inFlags) @@ -268,34 +268,33 @@ public class SignInfo { .build(); } - private static List parseMerkleTreeExtension(ByteBuffer bf, int inExtensionNum) + private static List parseExtensionList(ByteBuffer bf, int inExtensionNum) throws VerifyCodeSignException { List inExtensionList = new ArrayList<>(); - if (inExtensionNum >= 1) { - // parse merkle tree extension + for (int i = 0; i < inExtensionNum; i++) { int extensionType = bf.getInt(); - if (extensionType != MerkleTreeExtension.MERKLE_TREE_INLINED) { + if (extensionType == MerkleTreeExtension.MERKLE_TREE_INLINED) { + // parse merkle tree extension + int extensionSize = bf.getInt(); + if (extensionSize != (Extension.EXTENSION_HEADER_SIZE + + MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE)) { + throw new VerifyCodeSignException("Invalid extensionSize of SignInfo"); + } + byte[] merkleTreeExtension = new byte[MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE]; + bf.get(merkleTreeExtension); + inExtensionList.add(MerkleTreeExtension.fromByteArray(merkleTreeExtension)); + } else if (extensionType == PageInfoExtension.PAGE_INFO_INLINED) { + // parse page info extension + int extensionSize = bf.getInt(); + if (extensionSize <= (Extension.EXTENSION_HEADER_SIZE)) { + throw new VerifyCodeSignException("Invalid extensionSize of SignInfo"); + } + byte[] pageInfoExtension = new byte[extensionSize - Extension.EXTENSION_HEADER_SIZE]; + bf.get(pageInfoExtension); + inExtensionList.add(PageInfoExtension.fromByteArray(pageInfoExtension)); + } else { throw new VerifyCodeSignException("Invalid extensionType of SignInfo"); } - int extensionSize = bf.getInt(); - if (extensionSize != (Extension.EXTENSION_HEADER_SIZE - + MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE)) { - throw new VerifyCodeSignException("Invalid extensionSize of SignInfo"); - } - byte[] merkleTreeExtension = new byte[MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE]; - bf.get(merkleTreeExtension); - inExtensionList.add(MerkleTreeExtension.fromByteArray(merkleTreeExtension)); - } - if (inExtensionNum >= 2) { - // parse page info extension - int extensionType = bf.getInt(); - if (extensionType != PageInfoExtension.PAGE_INFO_INLINED) { - throw new VerifyCodeSignException("Invalid extensionType of SignInfo"); - } - int extensionSize = bf.getInt(); - byte[] pageInfoExtension = new byte[extensionSize - Extension.EXTENSION_HEADER_SIZE]; - bf.get(pageInfoExtension); - inExtensionList.add(PageInfoExtension.fromByteArray(pageInfoExtension)); } return inExtensionList; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java index 9fb144d4..e84d446c 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java @@ -31,7 +31,7 @@ import java.util.stream.Collectors; public class ElfFile { private ElfHeader elfHeader; - private final List list = new ArrayList<>(); + private final List programHeaderList = new ArrayList<>(); /** * Constructor for ElfFile @@ -45,9 +45,15 @@ public class ElfFile { byte eiClass = elfHeader.getEiClass(); byte eiData = elfHeader.getEiData(); short ePhnum = elfHeader.getEPhnum(); + long ePhOff = elfHeader.getEPhOff(); + if (eiClass == ElfDefine.ELF_32_CLASS) { + is.skip(ePhOff - ElfDefine.ELF_HEADER_32_LEN); + } else if (eiClass == ElfDefine.ELF_64_CLASS) { + is.skip(ePhOff - ElfDefine.ELF_HEADER_64_LEN); + } for (short i = 0; i < ePhnum; i++) { ElfProgramHeader pHeader = new ElfProgramHeader(is, eiClass, eiData); - list.add(pHeader); + programHeaderList.add(pHeader); } } @@ -57,6 +63,6 @@ public class ElfFile { * @return executable program segment headers */ public List filterExecPHeaders() { - return list.stream().filter(phdr -> (phdr.getPFlags() & 1) == 1).collect(Collectors.toList()); + return programHeaderList.stream().filter(phdr -> (phdr.getPFlags() & 1) == 1).collect(Collectors.toList()); } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java index b3377926..70f690a4 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java @@ -28,6 +28,9 @@ import java.nio.ByteOrder; * @since 2024/07/01 */ public class ElfHeader { + /** + * Magic number and other info + */ private byte[] ident = new byte[ElfDefine.EI_NIDENT_LEN]; private byte eiClass; @@ -36,30 +39,69 @@ public class ElfHeader { private byte eiVersion; + /** + * Object file type + */ private short eType; + /** + * Architecture + */ private int eMachine; + /** + * Object file version + */ private int eVersion; + /** + * Entry point virtual address + */ private long eEntry; + /** + * Program header table file offset + */ private long ePhOff; + /** + * Section header table file offset + */ private long eShOff; + /** + * Processor-specific flags + */ private int eFlags; + /** + * ELF header size in bytes + */ private short eEhSize; + /** + * Program header table entry size + */ private short ePhEntSize; + /** + * Program header table entry count + */ private short ePhNum; + /** + * Section header table entry size + */ private short eShEntSize; + /** + * Section header table entry count + */ private short eShNum; + /** + * Section header string table index + */ private short eShStrndx; /** @@ -70,14 +112,14 @@ public class ElfHeader { * @throws ElfFormatException elf file format error */ public ElfHeader(InputStream is) throws IOException, ElfFormatException { - is.read(ident); - if (!(ident[0] == 0x7F && ident[1] == 0x45 && ident[2] == 0x4C && ident[3] == 0x46)) { - return; + int read = is.read(ident); + if (read != ident.length || !(ident[0] == 0x7F && ident[1] == 0x45 && ident[2] == 0x4C && ident[3] == 0x46)) { + throw new ElfFormatException("Not a elf file"); } eiClass = ident[4]; eiData = ident[5]; eiVersion = ident[6]; - if (eiVersion != 1) { + if (eiVersion < 1) { throw new ElfFormatException("ELF eiVersion is incorrect"); } int len; @@ -97,7 +139,10 @@ public class ElfHeader { throw new ElfFormatException("ELF eiData is incorrect"); } byte[] bytes = new byte[len]; - is.read(bytes); + read = is.read(bytes); + if (read != len) { + throw new ElfFormatException("ELF file header is incorrect"); + } ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(bo); initHeader(byteBuffer); @@ -113,14 +158,14 @@ public class ElfHeader { ePhOff = byteBuffer.getInt() & 0xFFFFFFFFL; eShOff = byteBuffer.getInt() & 0xFFFFFFFFL; if (ePhOff != ElfDefine.ELF_HEADER_32_LEN) { - throw new ElfFormatException("ELF ePhOff is incorrect"); + throw new ElfFormatException("ELF Program header table file offset is incorrect"); } } else { eEntry = byteBuffer.getLong(); ePhOff = byteBuffer.getLong(); eShOff = byteBuffer.getLong(); if (ePhOff != ElfDefine.ELF_HEADER_64_LEN) { - throw new ElfFormatException("ELF ePhOff is incorrect"); + throw new ElfFormatException("ELF Program header table file offset is incorrect"); } } eFlags = byteBuffer.getInt(); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfProgramHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfProgramHeader.java index 8800d185..c1b3ffa7 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfProgramHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfProgramHeader.java @@ -28,20 +28,44 @@ import java.nio.ByteOrder; * @since 2024/07/01 */ public class ElfProgramHeader { + /** + * Segment type + */ private int pType; + /** + * Segment flags + */ private int pFlags; + /** + * Segment file offset + */ private long pOffset; + /** + * Segment virtual address + */ private long pVaddr; + /** + * Segment physical address + */ private long pPaddr; + /** + * Segment size in file + */ private long pFilesz; + /** + * Segment size in memory + */ private long pMemsz; + /** + * Segment alignment + */ private long pAlign; /** @@ -64,7 +88,10 @@ public class ElfProgramHeader { } if (eiClass == ElfDefine.ELF_32_CLASS) { byte[] bytes = new byte[ElfDefine.ELF_PHEADER_32_LEN]; - is.read(bytes); + int read = is.read(bytes); + if (read != ElfDefine.ELF_PHEADER_32_LEN) { + throw new ElfFormatException("ELF program header is incorrect"); + } ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(bo); pType = byteBuffer.getInt(); @@ -77,7 +104,10 @@ public class ElfProgramHeader { pAlign = byteBuffer.getInt(); } else { byte[] bytes = new byte[ElfDefine.ELF_PHEADER_64_LEN]; - is.read(bytes); + int read = is.read(bytes); + if (read != ElfDefine.ELF_PHEADER_64_LEN) { + throw new ElfFormatException("ELF program header is incorrect"); + } ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(bo); pType = byteBuffer.getInt(); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java index 8acc2081..2d3d044e 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java @@ -68,7 +68,7 @@ public class FsVerityDescriptor { /** * code sign version */ - public static final byte CODE_SIGN_VERSION_PAGE_INFO = 0x2; + public static final byte CODE_SIGN_VERSION_V2 = 0x2; /** * FsVerity descriptor size @@ -257,12 +257,12 @@ public class FsVerityDescriptor { buffer.putLong(fileSize); writeBytesWithSize(buffer, rawRootHash, ROOT_HASH_FILED_SIZE); writeBytesWithSize(buffer, salt, SALT_SIZE); - buffer.putInt((unitSize << 1 | 1)); + buffer.putInt((unitSize << 1 | flags)); buffer.putInt((int) mapSize); buffer.putLong(merkleTreeOffset); buffer.putLong(mapOffset); writeBytesWithSize(buffer, null, RESERVED_SIZE_AFTER_TREE_OFFSET); - buffer.put(CODE_SIGN_VERSION_PAGE_INFO); + buffer.put(CODE_SIGN_VERSION_V2); return buffer.array(); } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityGenerator.java index 8f0522d5..67c0a9e8 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityGenerator.java @@ -121,7 +121,7 @@ public class FsVerityGenerator { } catch (NoSuchAlgorithmException e) { throw new FsVerityDigestException("Invalid algorithm" + e.getMessage(), e); } - if (pageInfoExtension != null && fsvTreeOffset != 0) { + if (pageInfoExtension != null && flags != 0) { try { byte[] fsVerityDescriptorV2 = builder.build() .getDiscByteCsv2(pageInfoExtension.getMapOffset(), pageInfoExtension.getMapSize(), diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index eb1f8d9e..32c775d8 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -217,9 +217,8 @@ public class CodeSigning { long dataSize = 0L; for (ZipEntry entry : zip.getZipEntries()) { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); - if (EntryType.BitMap.equals(entry.getZipEntryData().getType()) || ( - FileUtils.isRunnableFile(zipEntryHeader.getFileName()) - && zipEntryHeader.getMethod() == Zip.FILE_UNCOMPRESS_METHOD_FLAG)) { + if (EntryType.BitMap.equals(entry.getZipEntryData().getType()) || EntryType.RunnableFile.equals( + entry.getZipEntryData().getType())) { continue; } // if the first file is not uncompressed abc or so, set dataSize to zero diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index ff0fc727..e7452cc7 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -59,7 +59,7 @@ public class PageInfoGenerator { private long maxEntryDataOffset = 0L; - private final List elfExcSegmentList = new ArrayList<>(); + private final List excSegmentList = new ArrayList<>(); /** * Constructor for PageInfoGenerator @@ -68,7 +68,7 @@ public class PageInfoGenerator { * @throws IOException io error * @throws ElfFormatException elf file format error */ - public PageInfoGenerator(File input) throws IOException, ElfFormatException { + public PageInfoGenerator(File input) throws IOException, ElfFormatException, HapFormatException { new PageInfoGenerator(new Zip(input)); } @@ -79,7 +79,7 @@ public class PageInfoGenerator { * @throws IOException io error * @throws ElfFormatException elf file format error */ - public PageInfoGenerator(Zip zip) throws IOException, ElfFormatException { + public PageInfoGenerator(Zip zip) throws IOException, ElfFormatException, HapFormatException { Map libNames = new LinkedHashMap<>(); List zipEntries = zip.getZipEntries(); for (ZipEntry entry : zipEntries) { @@ -87,12 +87,15 @@ public class PageInfoGenerator { long entryDataOffset = entry.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); if (entryDataOffset % PAGE_SIZE_4K != 0) { - break; + throw new HapFormatException( + String.format(Locale.ROOT, "Invalid entryDataOffset(%d), not a multiple of 4096", maxEntryDataOffset)); } - maxEntryDataOffset = entryDataOffset; if (EntryType.RunnableFile.equals(entry.getZipEntryData().getType())) { libNames.put(zipEntryHeader.getFileName(), entryDataOffset); + continue; } + maxEntryDataOffset = entryDataOffset; + break; } File input = new File(zip.getFile()); try (JarFile hap = new JarFile(input, false)) { @@ -107,7 +110,7 @@ public class PageInfoGenerator { JarEntry libEntry = hap.getJarEntry(libFileName); if (libFileName.endsWith(FileUtils.ABC_FILE_SUFFIX)) { long size = libEntry.getSize(); - elfExcSegmentList.add(new ElfExcSegment(libFileName, entryDataOffset, entryDataOffset + size)); + excSegmentList.add(new ExcSegment(ABC_M_CODE, libFileName, entryDataOffset, entryDataOffset + size)); } else { try (InputStream stream = hap.getInputStream(libEntry)) { ElfFile elfFile = new ElfFile(stream); @@ -117,8 +120,10 @@ public class PageInfoGenerator { long pFilesz = programHeader.getPFilesz(); long off = entryDataOffset + pOffset; long endoff = off + pFilesz; - elfExcSegmentList.add(new ElfExcSegment(libFileName, off, endoff)); + excSegmentList.add(new ExcSegment(ELF_M_CODE, libFileName, off, endoff)); } + } catch (ElfFormatException e) { + throw new ElfFormatException(libFileName + " error : " + e.getMessage(), e); } } } @@ -136,14 +141,13 @@ public class PageInfoGenerator { } int len = (int) (maxEntryDataOffset / PAGE_SIZE_1K); BitSet bitmap = new BitSet(len); - for (ElfExcSegment elf : elfExcSegmentList) { - int begin = (int) (elf.getPsStartOffset() / PAGE_SIZE_4K) * 4; - int end = (elf.getPsEndOffset() % PAGE_SIZE_4K == 0) - ? (int) ((elf.getPsEndOffset() / PAGE_SIZE_4K)) * 4 - : (int) ((elf.getPsEndOffset() / PAGE_SIZE_4K) + 1) * 4; - byte b = elf.getFileName().endsWith(FileUtils.ABC_FILE_SUFFIX) ? ABC_M_CODE : ELF_M_CODE; + for (ExcSegment es : excSegmentList) { + int begin = (int) (es.getStartOffset() >> 12) * PageInfoExtension.DEFAULT_UNIT_SIZE; + int end = (es.getEndOffset() % PAGE_SIZE_4K == 0) + ? (int) ((es.getEndOffset() >> 12)) * PageInfoExtension.DEFAULT_UNIT_SIZE + : (int) ((es.getEndOffset() >> 12) + 1) * PageInfoExtension.DEFAULT_UNIT_SIZE; for (int i = begin; i < end; i = i + 4) { - if ((ELF_M_CODE == b)) { + if ((ELF_M_CODE == es.getType())) { bitmap.set(i + 3); } else { bitmap.set(i + 2); @@ -176,29 +180,39 @@ public class PageInfoGenerator { return new long[0]; } - static class ElfExcSegment { + static class ExcSegment { + /** + * abc or elf + */ + private byte type; + private String fileName; - private long psStartOffset; + private long startOffset; - private long psEndOffset; + private long endOffset; - ElfExcSegment(String fileName, long psStartOffset, long psEndOffset) { + ExcSegment(byte type, String fileName, long startOffset, long endOffset) { + this.type = type; this.fileName = fileName; - this.psStartOffset = psStartOffset; - this.psEndOffset = psEndOffset; + this.startOffset = startOffset; + this.endOffset = endOffset; + } + + public byte getType() { + return type; } public String getFileName() { return fileName; } - public long getPsStartOffset() { - return psStartOffset; + public long getStartOffset() { + return startOffset; } - public long getPsEndOffset() { - return psEndOffset; + public long getEndOffset() { + return endOffset; } } } -- Gitee From 470e5886e33017c01aa482aad6a38b620c5709be Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Thu, 25 Jul 2024 09:16:17 +0800 Subject: [PATCH 24/26] bitmap generator Signed-off-by: zfeixiang --- .../hapsigntool/codesigning/elf/ElfHeader.java | 9 +++++++++ .../hapsigntool/codesigning/sign/CodeSigning.java | 4 ++-- .../codesigning/sign/PageInfoGenerator.java | 14 ++++++++++---- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java index 70f690a4..681a754c 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java @@ -33,10 +33,19 @@ public class ElfHeader { */ private byte[] ident = new byte[ElfDefine.EI_NIDENT_LEN]; + /** + * 32-bit or 64-bit file + */ private byte eiClass; + /** + * LITTLE_ENDIAN or BIG_ENDIAN + */ private byte eiData; + /** + * elf version + */ private byte eiVersion; /** diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java index 32c775d8..3792e356 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/CodeSigning.java @@ -217,8 +217,8 @@ public class CodeSigning { long dataSize = 0L; for (ZipEntry entry : zip.getZipEntries()) { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); - if (EntryType.BitMap.equals(entry.getZipEntryData().getType()) || EntryType.RunnableFile.equals( - entry.getZipEntryData().getType())) { + EntryType type = entry.getZipEntryData().getType(); + if (EntryType.BitMap.equals(type) || EntryType.RunnableFile.equals(type)) { continue; } // if the first file is not uncompressed abc or so, set dataSize to zero diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java index e7452cc7..85214c96 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -32,6 +32,7 @@ import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.BitSet; import java.util.LinkedHashMap; @@ -80,7 +81,7 @@ public class PageInfoGenerator { * @throws ElfFormatException elf file format error */ public PageInfoGenerator(Zip zip) throws IOException, ElfFormatException, HapFormatException { - Map libNames = new LinkedHashMap<>(); + Map runnableFileNames = new LinkedHashMap<>(); List zipEntries = zip.getZipEntries(); for (ZipEntry entry : zipEntries) { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); @@ -91,7 +92,7 @@ public class PageInfoGenerator { String.format(Locale.ROOT, "Invalid entryDataOffset(%d), not a multiple of 4096", maxEntryDataOffset)); } if (EntryType.RunnableFile.equals(entry.getZipEntryData().getType())) { - libNames.put(zipEntryHeader.getFileName(), entryDataOffset); + runnableFileNames.put(zipEntryHeader.getFileName(), entryDataOffset); continue; } maxEntryDataOffset = entryDataOffset; @@ -99,7 +100,7 @@ public class PageInfoGenerator { } File input = new File(zip.getFile()); try (JarFile hap = new JarFile(input, false)) { - for (Map.Entry en : libNames.entrySet()) { + for (Map.Entry en : runnableFileNames.entrySet()) { this.libExecSegment(hap, en.getKey(), en.getValue()); } } @@ -154,7 +155,12 @@ public class PageInfoGenerator { } } } - return bitmap.toByteArray(); + long[] longArray = bitmap.toLongArray(); + ByteBuffer buffer = ByteBuffer.allocate(longArray.length * 8); + for (long l : longArray) { + buffer.putLong(Long.reverse(l)); + } + return buffer.array(); } /** -- Gitee From ab3872912e515a8e9fbad0039beb928d5623460b Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Thu, 25 Jul 2024 11:25:51 +0800 Subject: [PATCH 25/26] only hap sign bitmap Signed-off-by: wangzeyu --- .../hap/provider/SignProvider.java | 2 +- .../zip/EndOfCentralDirectory.java | 12 +++++----- .../java/com/ohos/hapsigntool/zip/Zip.java | 22 +++++++++---------- .../com/ohos/hapsigntool/zip/ZipEntry.java | 9 ++++---- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index b27202dc..8433fa37 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -509,7 +509,7 @@ public abstract class SignProvider { throws IOException, HapFormatException, ElfFormatException { Zip zip = new Zip(input); zip.alignment(alignment); - if (suffix.equals("hap")) { + if ("hap".equals(suffix)) { PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); byte[] bitMap = pageInfoGenerator.generateBitMap(); if (bitMap != null) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EndOfCentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EndOfCentralDirectory.java index 92d211b3..6936dadf 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EndOfCentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EndOfCentralDirectory.java @@ -123,8 +123,8 @@ public class EndOfCentralDirectory { eocd.setDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); eocd.setcDStartDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); eocd.setThisDiskCDNum(UnsignedDecimalUtil.getUnsignedShort(bf)); - eocd.setcDTotal(UnsignedDecimalUtil.getUnsignedShort(bf)); - eocd.setcDSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + eocd.setCDTotal(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setCDSize(UnsignedDecimalUtil.getUnsignedInt(bf)); eocd.setOffset(UnsignedDecimalUtil.getUnsignedInt(bf)); eocd.setCommentLength(UnsignedDecimalUtil.getUnsignedShort(bf)); if (bf.remaining() != eocd.getCommentLength()) { @@ -195,19 +195,19 @@ public class EndOfCentralDirectory { this.thisDiskCDNum = thisDiskCDNum; } - public int getcDTotal() { + public int getCDTotal() { return cDTotal; } - public void setcDTotal(int cDTotal) { + public void setCDTotal(int cDTotal) { this.cDTotal = cDTotal; } - public long getcDSize() { + public long getCDSize() { return cDSize; } - public void setcDSize(long cDSize) { + public void setCDSize(long cDSize) { this.cDSize = cDSize; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index 3b016a68..55cfe952 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -63,7 +63,6 @@ public class Zip { private String file; - /** * create Zip by file * @@ -129,9 +128,9 @@ public class Zip { } private void getZipCentralDirectory(File file) throws IOException { - zipEntries = new ArrayList<>(endOfCentralDirectory.getcDTotal()); + zipEntries = new ArrayList<>(endOfCentralDirectory.getCDTotal()); // read full central directory bytes - byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, cDOffset, endOfCentralDirectory.getcDSize()); + byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, cDOffset, endOfCentralDirectory.getCDSize()); if (cdBytes.length < CentralDirectory.CD_LENGTH) { throw new ZipException("find zip cd failed"); } @@ -261,6 +260,8 @@ public class Zip { for (ZipEntry e : zipEntries) { if (e.getZipEntryData().getType() == EntryType.BitMap) { e.getZipEntryData().setData(data); + e.getZipEntryData().getZipEntryHeader().setUnCompressedSize(data.length); + e.getZipEntryData().getZipEntryHeader().setCompressedSize(data.length); return; } } @@ -287,17 +288,16 @@ public class Zip { private void sort() { // sort uncompress file (so, abc, an) - bitmap - other uncompress file - compress file zipEntries.sort((entry1, entry2) -> { - EntryType entry1Type = entry1.getZipEntryData().getType(); - EntryType entry2Type = entry2.getZipEntryData().getType(); - if (entry1Type != entry2Type) { - return entry1Type.compareTo(entry2Type); - } - short entry1Method = entry1.getZipEntryData().getZipEntryHeader().getMethod(); short entry2Method = entry2.getZipEntryData().getZipEntryHeader().getMethod(); String entry1FileName = entry1.getZipEntryData().getZipEntryHeader().getFileName(); String entry2FileName = entry2.getZipEntryData().getZipEntryHeader().getFileName(); if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG && entry2Method == FILE_UNCOMPRESS_METHOD_FLAG) { + EntryType entry1Type = entry1.getZipEntryData().getType(); + EntryType entry2Type = entry2.getZipEntryData().getType(); + if (entry1Type != entry2Type) { + return entry1Type.compareTo(entry2Type); + } return entry1FileName.compareTo(entry2FileName); } else if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG) { return -1; @@ -323,10 +323,10 @@ public class Zip { } cDOffset = offset; endOfCentralDirectory.setOffset(offset); - endOfCentralDirectory.setcDSize(cdLength); + endOfCentralDirectory.setCDSize(cdLength); offset += cdLength; eOCDOffset = offset; - endOfCentralDirectory.setcDTotal(zipEntries.size()); + endOfCentralDirectory.setCDTotal(zipEntries.size()); endOfCentralDirectory.setThisDiskCDNum(zipEntries.size()); } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java index 82d7a2fb..03682ddd 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java @@ -205,10 +205,11 @@ public class ZipEntry { cd.setMethod(method); zipEntryHeader.setMethod(method); - cd.setLastTime((short) 0); - cd.setLastDate((short) 20001); - zipEntryHeader.setLastTime((short) 0); - zipEntryHeader.setLastDate((short) 20001); + long time = System.currentTimeMillis(); + cd.setLastTime((short) (time >> 32)); + cd.setLastDate((short) time); + zipEntryHeader.setLastTime((short) (time >> 32)); + zipEntryHeader.setLastDate((short) time); cd.setCompressedSize(compressedSize); zipEntryHeader.setCompressedSize(compressedSize); -- Gitee From 4cbd6ecd6b690e9b40555575e81fc89179a8c3ed Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Thu, 25 Jul 2024 11:25:51 +0800 Subject: [PATCH 26/26] only hap sign bitmap Signed-off-by: wangzeyu --- .../hap/provider/SignProvider.java | 2 +- .../zip/EndOfCentralDirectory.java | 12 +++++----- .../java/com/ohos/hapsigntool/zip/Zip.java | 22 +++++++++---------- .../com/ohos/hapsigntool/zip/ZipEntry.java | 9 ++++---- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index b27202dc..8433fa37 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -509,7 +509,7 @@ public abstract class SignProvider { throws IOException, HapFormatException, ElfFormatException { Zip zip = new Zip(input); zip.alignment(alignment); - if (suffix.equals("hap")) { + if ("hap".equals(suffix)) { PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); byte[] bitMap = pageInfoGenerator.generateBitMap(); if (bitMap != null) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EndOfCentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EndOfCentralDirectory.java index 92d211b3..6936dadf 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EndOfCentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/EndOfCentralDirectory.java @@ -123,8 +123,8 @@ public class EndOfCentralDirectory { eocd.setDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); eocd.setcDStartDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); eocd.setThisDiskCDNum(UnsignedDecimalUtil.getUnsignedShort(bf)); - eocd.setcDTotal(UnsignedDecimalUtil.getUnsignedShort(bf)); - eocd.setcDSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + eocd.setCDTotal(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setCDSize(UnsignedDecimalUtil.getUnsignedInt(bf)); eocd.setOffset(UnsignedDecimalUtil.getUnsignedInt(bf)); eocd.setCommentLength(UnsignedDecimalUtil.getUnsignedShort(bf)); if (bf.remaining() != eocd.getCommentLength()) { @@ -195,19 +195,19 @@ public class EndOfCentralDirectory { this.thisDiskCDNum = thisDiskCDNum; } - public int getcDTotal() { + public int getCDTotal() { return cDTotal; } - public void setcDTotal(int cDTotal) { + public void setCDTotal(int cDTotal) { this.cDTotal = cDTotal; } - public long getcDSize() { + public long getCDSize() { return cDSize; } - public void setcDSize(long cDSize) { + public void setCDSize(long cDSize) { this.cDSize = cDSize; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java index 3b016a68..55cfe952 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/Zip.java @@ -63,7 +63,6 @@ public class Zip { private String file; - /** * create Zip by file * @@ -129,9 +128,9 @@ public class Zip { } private void getZipCentralDirectory(File file) throws IOException { - zipEntries = new ArrayList<>(endOfCentralDirectory.getcDTotal()); + zipEntries = new ArrayList<>(endOfCentralDirectory.getCDTotal()); // read full central directory bytes - byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, cDOffset, endOfCentralDirectory.getcDSize()); + byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, cDOffset, endOfCentralDirectory.getCDSize()); if (cdBytes.length < CentralDirectory.CD_LENGTH) { throw new ZipException("find zip cd failed"); } @@ -261,6 +260,8 @@ public class Zip { for (ZipEntry e : zipEntries) { if (e.getZipEntryData().getType() == EntryType.BitMap) { e.getZipEntryData().setData(data); + e.getZipEntryData().getZipEntryHeader().setUnCompressedSize(data.length); + e.getZipEntryData().getZipEntryHeader().setCompressedSize(data.length); return; } } @@ -287,17 +288,16 @@ public class Zip { private void sort() { // sort uncompress file (so, abc, an) - bitmap - other uncompress file - compress file zipEntries.sort((entry1, entry2) -> { - EntryType entry1Type = entry1.getZipEntryData().getType(); - EntryType entry2Type = entry2.getZipEntryData().getType(); - if (entry1Type != entry2Type) { - return entry1Type.compareTo(entry2Type); - } - short entry1Method = entry1.getZipEntryData().getZipEntryHeader().getMethod(); short entry2Method = entry2.getZipEntryData().getZipEntryHeader().getMethod(); String entry1FileName = entry1.getZipEntryData().getZipEntryHeader().getFileName(); String entry2FileName = entry2.getZipEntryData().getZipEntryHeader().getFileName(); if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG && entry2Method == FILE_UNCOMPRESS_METHOD_FLAG) { + EntryType entry1Type = entry1.getZipEntryData().getType(); + EntryType entry2Type = entry2.getZipEntryData().getType(); + if (entry1Type != entry2Type) { + return entry1Type.compareTo(entry2Type); + } return entry1FileName.compareTo(entry2FileName); } else if (entry1Method == FILE_UNCOMPRESS_METHOD_FLAG) { return -1; @@ -323,10 +323,10 @@ public class Zip { } cDOffset = offset; endOfCentralDirectory.setOffset(offset); - endOfCentralDirectory.setcDSize(cdLength); + endOfCentralDirectory.setCDSize(cdLength); offset += cdLength; eOCDOffset = offset; - endOfCentralDirectory.setcDTotal(zipEntries.size()); + endOfCentralDirectory.setCDTotal(zipEntries.size()); endOfCentralDirectory.setThisDiskCDNum(zipEntries.size()); } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java index 82d7a2fb..03682ddd 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java @@ -205,10 +205,11 @@ public class ZipEntry { cd.setMethod(method); zipEntryHeader.setMethod(method); - cd.setLastTime((short) 0); - cd.setLastDate((short) 20001); - zipEntryHeader.setLastTime((short) 0); - zipEntryHeader.setLastDate((short) 20001); + long time = System.currentTimeMillis(); + cd.setLastTime((short) (time >> 32)); + cd.setLastDate((short) time); + zipEntryHeader.setLastTime((short) (time >> 32)); + zipEntryHeader.setLastDate((short) time); cd.setCompressedSize(compressedSize); zipEntryHeader.setCompressedSize(compressedSize); -- Gitee