From 1c6621e43663b2565e22943e8bc9a098566d2920 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Thu, 25 Jul 2024 14:46:22 +0800 Subject: [PATCH 01/28] only hap sign bitmap Signed-off-by: wangzeyu --- .../hapsigntool/zip/CentralDirectory.java | 9 +- .../com/ohos/hapsigntool/zip/EntryType.java | 26 +++ .../java/com/ohos/hapsigntool/zip/Zip.java | 50 ++++-- .../com/ohos/hapsigntool/zip/ZipEntry.java | 164 ++++++++++++++++-- .../ohos/hapsigntool/zip/ZipEntryData.java | 32 ++++ .../ohos/hapsigntool/zip/ZipEntryHeader.java | 9 +- 6 files changed, 264 insertions(+), 26 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..828543e8 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 @@ -43,7 +43,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 +172,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 +195,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 +263,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 +285,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 +313,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 +326,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 dd8a7aae14de429742b646502cb0b5a33c41d05a Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Thu, 25 Jul 2024 19:21:40 +0800 Subject: [PATCH 02/28] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/datastructure/Extension.java | 6 +- .../datastructure/HapInfoSegment.java | 2 +- .../datastructure/MerkleTreeExtension.java | 5 +- .../datastructure/PageInfoExtension.java | 171 +++++++++++++ .../codesigning/datastructure/SignInfo.java | 39 +-- .../codesigning/elf/ElfDefine.java | 68 ++++++ .../hapsigntool/codesigning/elf/ElfFile.java | 68 ++++++ .../codesigning/elf/ElfHeader.java | 204 ++++++++++++++++ .../codesigning/elf/ElfProgramHeader.java | 135 +++++++++++ .../exception/ElfFormatException.java | 31 +++ .../fsverity/FsVerityDescriptor.java | 60 ++++- .../fsverity/FsVerityGenerator.java | 48 +++- .../codesigning/sign/CodeSigning.java | 30 ++- .../codesigning/sign/PageInfoGenerator.java | 224 ++++++++++++++++++ .../hap/provider/SignProvider.java | 21 +- .../com/ohos/hapsigntool/utils/FileUtils.java | 17 +- 16 files changed, 1082 insertions(+), 47 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java 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/ElfProgramHeader.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/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/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/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 new file mode 100644 index 00000000..4dae86b5 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/datastructure/PageInfoExtension.java @@ -0,0 +1,171 @@ +/* + * 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 com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; + +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: 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 . + *

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

+ * 6) u32 signSize: signature size + *

+ * 7) u8[] signature: signature of the data + * + * @since 2024/07/01 + */ +public class PageInfoExtension extends Extension { + /** + * Type of PageInfoExtension + */ + public static final int PAGE_INFO_INLINED = 0x2; + + /** + * Byte size of PageInfoExtension + */ + public static final int PAGE_INFO_EXTENSION_DATA_SIZE_WITHOUT_SIGN = 24; + + /** + * default unit size + */ + public static final int DEFAULT_UNIT_SIZE = 4; + + private static final int RESERVED_SIZE = 3; + + private static final int SIGNATURE_ALIGNMENT = 4; + + private long mapOffset; + + private long mapSize; + + private byte unitSize; + + 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 + * + * @param mapOffset bitmap offset + * @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); + 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 + * + * @return Byte size of PageInfoExtension + */ + @Override + public int size() { + return Extension.EXTENSION_HEADER_SIZE + PAGE_INFO_EXTENSION_DATA_SIZE_WITHOUT_SIGN + signSize + + zeroPadding.length; + } + + /** + * Converts PageInfoExtension to a newly created byte array + * + * @return Byte array representation of PageInfoExtension + */ + @Override + public byte[] toByteArray() { + 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(); + } + + /** + * Init the PageInfoExtension by a byte array + * + * @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 inMapOffset = bf.getLong(); + if (inMapOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { + throw new VerifyCodeSignException("mapOffset is not a multiple of 4096"); + } + long inMapSize = bf.getLong(); + byte inUnitSize = bf.get(); + if (inMapSize % inUnitSize != 0) { + throw new VerifyCodeSignException("mapSize is not a multiple of unitSize"); + } + bf.get(new byte[RESERVED_SIZE]); + int inSignSize = bf.getInt(); + byte[] inSignature = new byte[inSignSize]; + bf.get(inSignature); + PageInfoExtension extension = new PageInfoExtension(inMapOffset, inMapSize); + extension.unitSize = inUnitSize; + extension.setSignature(inSignature); + 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 e2d538c4..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 @@ -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 @@ -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 = this.size(); 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,22 +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 != 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)); } 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 new file mode 100644 index 00000000..288d5dae --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfDefine.java @@ -0,0 +1,68 @@ +/* + * 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; + +/** + * ELF struct define + * + * @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 new file mode 100644 index 00000000..e84d446c --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfFile.java @@ -0,0 +1,68 @@ +/* + * 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; + +/** + * ELF file + * + * @since 2024/07/01 + */ +public class ElfFile { + private ElfHeader elfHeader; + + private final List programHeaderList = new ArrayList<>(); + + /** + * Constructor for ElfFile + * + * @param is InputStream + * @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(); + 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); + programHeaderList.add(pHeader); + } + } + + /** + * filter executable program segment headers + * + * @return executable program segment headers + */ + public List filterExecPHeaders() { + 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 new file mode 100644 index 00000000..681a754c --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java @@ -0,0 +1,204 @@ +/* + * 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 header info + * + * @since 2024/07/01 + */ +public class ElfHeader { + /** + * Magic number and other info + */ + 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; + + /** + * 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; + + /** + * 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)) { + throw new ElfFormatException("Not a elf file"); + } + eiClass = ident[4]; + eiData = ident[5]; + eiVersion = ident[6]; + if (eiVersion < 1) { + throw new ElfFormatException("ELF eiVersion is incorrect"); + } + 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 eiClass is incorrect"); + } + ByteOrder bo; + 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 eiData is incorrect"); + } + byte[] bytes = new byte[len]; + 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); + } + + private void initHeader(ByteBuffer byteBuffer) throws ElfFormatException { + 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 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 Program header table file offset is incorrect"); + } + } + 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 eiClass; + } + + public byte getEiData() { + return eiData; + } + + public long getEPhOff() { + return ePhOff; + } + + public short getEPhnum() { + return ePhNum; + } +} 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 new file mode 100644 index 00000000..c1b3ffa7 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/elf/ElfProgramHeader.java @@ -0,0 +1,135 @@ +/* + * 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 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; + + /** + * Constructor for ElfPHeader + * + * @param is InputStream + * @param eiClass eiClass + * @param eiData eiData + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ + 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; + } 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]; + 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(); + 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]; + 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(); + 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/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..1089f073 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/exception/ElfFormatException.java @@ -0,0 +1,31 @@ +/* + * 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; + +/** + * Elf format exception + * + * @since 2024/07/01 + */ +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/fsverity/FsVerityDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/fsverity/FsVerityDescriptor.java index 5531b7f8..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 @@ -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_V2 = 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) { @@ -152,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(); @@ -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 | flags)); + buffer.putInt((int) mapSize); buffer.putLong(merkleTreeOffset); + buffer.putLong(mapOffset); + writeBytesWithSize(buffer, null, RESERVED_SIZE_AFTER_TREE_OFFSET); + buffer.put(CODE_SIGN_VERSION_V2); 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..f4199038 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 void setPageInfoExtension(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 && flags != 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 c450dd11..9afc9914 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; @@ -34,6 +35,7 @@ import com.ohos.hapsigntool.hap.config.SignerConfig; 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; @@ -79,14 +81,12 @@ 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; + private PageInfoExtension pageInfoExtension; + /** * provide code sign functions to sign a hap * @@ -181,7 +181,7 @@ 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); @@ -207,12 +207,19 @@ public class CodeSigning { return generated; } + private void createPageInfoExtension(Zip zip) { + long[] bitmapOffSize = PageInfoGenerator.getPageInfoFromZip(zip); + if (bitmapOffSize.length == 2) { + pageInfoExtension = new PageInfoExtension(bitmapOffSize[0], bitmapOffSize[1]); + } + } + 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) { + 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 @@ -375,7 +382,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)) { @@ -438,6 +445,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.setPageInfoExtension(pageInfoExtension); fsVerityGenerator.generateFsVerityDigest(inputStream, fileSize, fsvTreeOffset); byte[] fsVerityDigest = fsVerityGenerator.getFsVerityDigest(); byte[] signature = generateSignature(fsVerityDigest, ownerID); @@ -453,6 +461,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 new file mode 100644 index 00000000..8a2549f0 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/sign/PageInfoGenerator.java @@ -0,0 +1,224 @@ +/* + * 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.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; +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.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.BitSet; +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; + +/** + * pages info bitmap generator + * + * @since 2024/07/01 + */ +public class PageInfoGenerator { + private static final byte ABC_M_CODE = 2; + + private static final byte ELF_M_CODE = 1; + + private static final long PAGE_SIZE_4K = 4096L; + + private static final long PAGE_SIZE_1K = PAGE_SIZE_4K / PageInfoExtension.DEFAULT_UNIT_SIZE; + + private static final Logger LOGGER = LogManager.getLogger(PageInfoGenerator.class); + + private long maxEntryDataOffset = 0L; + + private final List excSegmentList = new ArrayList<>(); + + /** + * Constructor for PageInfoGenerator + * + * @param input file + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ + public PageInfoGenerator(File input) throws IOException, ElfFormatException, HapFormatException { + new PageInfoGenerator(new Zip(input)); + } + + /** + * Constructor for PageInfoGenerator + * + * @param zip zip + * @throws IOException io error + * @throws ElfFormatException elf file format error + */ + public PageInfoGenerator(Zip zip) throws IOException, ElfFormatException, HapFormatException { + Map runnableFileNames = 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 % PAGE_SIZE_4K != 0) { + throw new HapFormatException( + String.format(Locale.ROOT, "Invalid entryDataOffset(%d), not a multiple of 4096", entryDataOffset)); + } + if (EntryType.RunnableFile.equals(entry.getZipEntryData().getType())) { + runnableFileNames.put(zipEntryHeader.getFileName(), entryDataOffset); + continue; + } + maxEntryDataOffset = entryDataOffset; + break; + } + File input = new File(zip.getFile()); + try (JarFile hap = new JarFile(input, false)) { + for (Map.Entry en : runnableFileNames.entrySet()) { + this.libExecSegment(hap, en.getKey(), en.getValue()); + } + } + } + + private void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) + throws IOException, ElfFormatException { + JarEntry libEntry = hap.getJarEntry(libFileName); + if (libFileName.endsWith(FileUtils.ABC_FILE_SUFFIX)) { + long size = libEntry.getSize(); + excSegmentList.add(new ExcSegment(ABC_M_CODE, libFileName, entryDataOffset, entryDataOffset + size)); + } else { + try (InputStream stream = hap.getInputStream(libEntry)) { + ElfFile elfFile = new ElfFile(stream); + List elfPHeaders = elfFile.filterExecPHeaders(); + for (ElfProgramHeader programHeader : elfPHeaders) { + long pOffset = programHeader.getPOffset(); + long pFilesz = programHeader.getPFilesz(); + long off = entryDataOffset + pOffset; + long endoff = off + pFilesz; + excSegmentList.add(new ExcSegment(ELF_M_CODE, libFileName, off, endoff)); + } + } catch (ElfFormatException e) { + throw new ElfFormatException(libFileName + " error : " + e.getMessage(), e); + } + } + } + + /** + * generate bitMap + * + * @return byte array of bitmap + * @throws HapFormatException hap format error + */ + public byte[] generateBitMap() throws HapFormatException { + if (maxEntryDataOffset % PAGE_SIZE_4K != 0) { + throw new HapFormatException( + String.format(Locale.ROOT, "Invalid maxEndOff(%d), not a multiple of 4096", maxEntryDataOffset)); + } + int len = (int) (maxEntryDataOffset / PAGE_SIZE_1K); + BitSet bitmap = new BitSet(len); + 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 == es.getType())) { + bitmap.set(i + 3); + } else { + bitmap.set(i + 2); + } + } + } + long[] longArray = bitmap.toLongArray(); + ByteBuffer buffer = ByteBuffer.allocate(longArray.length * 8); + for (long l : longArray) { + buffer.putLong(Long.reverse(l)); + } + return buffer.array(); + } + + /** + * 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) { + String fileName = e.getCentralDirectory().getFileName(); + if (!FileUtils.BIT_MAP_FILENAME.equals(fileName)) { + continue; + } + long fileOffset = e.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + e.getZipEntryData() + .getZipEntryHeader() + .getFileNameLength() + e.getZipEntryData().getZipEntryHeader().getExtraLength(); + long fileSize = e.getCentralDirectory().getUnCompressedSize(); + long bitmapSize = fileSize * 8; + return new long[] {fileOffset, bitmapSize}; + } + return new long[0]; + } + + static class ExcSegment { + /** + * abc or elf + */ + private byte type; + + private String fileName; + + private long startOffset; + + private long endOffset; + + ExcSegment(byte type, String fileName, long startOffset, long endOffset) { + this.type = type; + this.fileName = fileName; + this.startOffset = startOffset; + this.endOffset = endOffset; + } + + public byte getType() { + return type; + } + + public String getFileName() { + return fileName; + } + + public long getStartOffset() { + return startOffset; + } + + public long getEndOffset() { + return endOffset; + } + } +} 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..bd9904b2 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; @@ -336,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); @@ -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); @@ -501,10 +504,18 @@ public abstract class SignProvider { * @throws IOException io error * @throws HapFormatException hap format error */ - private Zip copyFileAndAlignment(File input, File tmpOutput, int alignment) - throws IOException, HapFormatException { + private Zip copyFileAndAlignment(File input, File tmpOutput, int alignment, String suffix) + throws IOException, HapFormatException, ElfFormatException { Zip zip = new Zip(input); zip.alignment(alignment); + if ("hap".equals(suffix)) { + PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); + byte[] bitMap = pageInfoGenerator.generateBitMap(); + if (bitMap != null) { + 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/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)) { -- Gitee From fbaeb87c3bc3f08638484f39a816509482f07385 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Thu, 25 Jul 2024 19:42:07 +0800 Subject: [PATCH 03/28] only hap sign bitmap Signed-off-by: wangzeyu --- .../src/main/java/com/ohos/hapsigntool/zip/Zip.java | 7 +++---- 1 file changed, 3 insertions(+), 4 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 828543e8..6e9db735 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 @@ -235,14 +235,13 @@ public class Zip { boolean isFirstUnRunnableFile = true; for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); - short method = zipEntryData.getZipEntryHeader().getMethod(); - if (method != FILE_UNCOMPRESS_METHOD_FLAG && !isFirstUnRunnableFile) { + EntryType type = zipEntryData.getType(); + if (type != EntryType.ResourceFile && !isFirstUnRunnableFile) { // only align uncompressed entry and the first compress entry. break; } int alignBytes; - if (method == FILE_UNCOMPRESS_METHOD_FLAG && FileUtils.isRunnableFile( - zipEntryData.getZipEntryHeader().getFileName())) { + if (type != EntryType.ResourceFile) { // .abc and .so file align 4096 byte. alignBytes = 4096; } else if (isFirstUnRunnableFile) { -- Gitee From 36e1bca27628be94e37a29a03cc0351c7f6eec26 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Thu, 25 Jul 2024 19:50:55 +0800 Subject: [PATCH 04/28] only hap sign bitmap Signed-off-by: wangzeyu --- .../zip/EndOfCentralDirectory.java | 12 +++---- .../java/com/ohos/hapsigntool/zip/Zip.java | 31 ++++++++++--------- .../com/ohos/hapsigntool/zip/ZipEntry.java | 9 +++--- .../ohos/hapsigntool/zip/ZipEntryData.java | 12 ++++++- 4 files changed, 39 insertions(+), 25 deletions(-) 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 6e9db735..4dd39574 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 @@ -129,9 +129,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"); } @@ -172,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"); } @@ -235,13 +229,14 @@ public class Zip { boolean isFirstUnRunnableFile = true; for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); - EntryType type = zipEntryData.getType(); - if (type != EntryType.ResourceFile && !isFirstUnRunnableFile) { + short method = zipEntryData.getZipEntryHeader().getMethod(); + if (method != FILE_UNCOMPRESS_METHOD_FLAG && !isFirstUnRunnableFile) { // only align uncompressed entry and the first compress entry. break; } int alignBytes; - if (type != EntryType.ResourceFile) { + EntryType type = entry.getZipEntryData().getType(); + if (type == EntryType.RunnableFile || type == EntryType.BitMap) { // .abc and .so file align 4096 byte. alignBytes = 4096; } else if (isFirstUnRunnableFile) { @@ -263,10 +258,18 @@ public class Zip { } public void addBitMap(byte[] data) throws ZipException { + 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; + } + } ZipEntry entry = new ZipEntry.Builder().setMethod(FILE_UNCOMPRESS_METHOD_FLAG) .setUncompressedSize(data.length) .setCompressedSize(data.length) - .setFileName("pages.info") + .setFileName(FileUtils.BIT_MAP_FILENAME) .setData(data) .build(); zipEntries.add(entry); @@ -322,10 +325,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); 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 6716eeb605771c6b0fcc70bed6d75584c6825a65 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Thu, 25 Jul 2024 20:42:19 +0800 Subject: [PATCH 05/28] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/sign/PageInfoGenerator.java | 20 ++++--------------- .../hap/provider/SignProvider.java | 7 +++---- 2 files changed, 7 insertions(+), 20 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 8a2549f0..be8ec455 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 @@ -62,25 +62,14 @@ public class PageInfoGenerator { private final List excSegmentList = new ArrayList<>(); - /** - * Constructor for PageInfoGenerator - * - * @param input file - * @throws IOException io error - * @throws ElfFormatException elf file format error - */ - public PageInfoGenerator(File input) throws IOException, ElfFormatException, HapFormatException { - new PageInfoGenerator(new Zip(input)); - } - /** * Constructor for PageInfoGenerator * * @param zip zip * @throws IOException io error - * @throws ElfFormatException elf file format error + * @throws HapFormatException hap file format error */ - public PageInfoGenerator(Zip zip) throws IOException, ElfFormatException, HapFormatException { + public PageInfoGenerator(Zip zip) throws IOException, HapFormatException { Map runnableFileNames = new LinkedHashMap<>(); List zipEntries = zip.getZipEntries(); for (ZipEntry entry : zipEntries) { @@ -106,8 +95,7 @@ public class PageInfoGenerator { } } - private void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) - throws IOException, ElfFormatException { + private void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) throws IOException { JarEntry libEntry = hap.getJarEntry(libFileName); if (libFileName.endsWith(FileUtils.ABC_FILE_SUFFIX)) { long size = libEntry.getSize(); @@ -124,7 +112,7 @@ public class PageInfoGenerator { excSegmentList.add(new ExcSegment(ELF_M_CODE, libFileName, off, endoff)); } } catch (ElfFormatException e) { - throw new ElfFormatException(libFileName + " error : " + e.getMessage(), e); + LOGGER.info(libFileName + " error : " + e.getMessage()); } } } 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 bd9904b2..39c80015 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 @@ -365,9 +365,8 @@ public abstract class SignProvider { outputSignedFile(outputHap, centralDirectoryOffset, signingBlock, centralDirectory, eocdBuffer); isRet = true; } - } catch (FsVerityDigestException | InvalidKeyException | HapFormatException | MissingParamsException | - InvalidParamsException | ProfileException | NumberFormatException | CustomException | IOException | - CodeSignException | ElfFormatException e) { + } catch (FsVerityDigestException | InvalidKeyException | HapFormatException | MissingParamsException +|InvalidParamsException |ProfileException |NumberFormatException |CustomException |IOException |CodeSignException e) { printErrorLogWithoutStack(e); } catch (SignatureException e) { printErrorLog(e); @@ -505,7 +504,7 @@ public abstract class SignProvider { * @throws HapFormatException hap format error */ private Zip copyFileAndAlignment(File input, File tmpOutput, int alignment, String suffix) - throws IOException, HapFormatException, ElfFormatException { + throws IOException, HapFormatException { Zip zip = new Zip(input); zip.alignment(alignment); if ("hap".equals(suffix)) { -- Gitee From c9e7671cbd0683c9ec7079f66a546877f1ed27f4 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Thu, 25 Jul 2024 23:08:53 +0800 Subject: [PATCH 06/28] bitmap generator Signed-off-by: zfeixiang --- .../hapsigntool/codesigning/sign/PageInfoGenerator.java | 9 +++++---- 1 file changed, 5 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 be8ec455..fa086c4d 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.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.ArrayList; import java.util.BitSet; import java.util.LinkedHashMap; @@ -137,16 +138,16 @@ public class PageInfoGenerator { : (int) ((es.getEndOffset() >> 12) + 1) * PageInfoExtension.DEFAULT_UNIT_SIZE; for (int i = begin; i < end; i = i + 4) { if ((ELF_M_CODE == es.getType())) { - bitmap.set(i + 3); + bitmap.set(i); } else { - bitmap.set(i + 2); + bitmap.set(i + 1); } } } long[] longArray = bitmap.toLongArray(); - ByteBuffer buffer = ByteBuffer.allocate(longArray.length * 8); + ByteBuffer buffer = ByteBuffer.allocate(longArray.length * 8).order(ByteOrder.LITTLE_ENDIAN); for (long l : longArray) { - buffer.putLong(Long.reverse(l)); + buffer.putLong(l); } return buffer.array(); } -- Gitee From 70e85b105f32a86e60ce656e3bb6b6d663b5a6be Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Fri, 26 Jul 2024 10:57:43 +0800 Subject: [PATCH 07/28] clean code Signed-off-by: zfeixiang --- .../hapsigntool/codesigning/elf/ElfHeader.java | 15 ++++++++++++++- .../codesigning/fsverity/FsVerityGenerator.java | 6 ------ .../hapsigntool/codesigning/sign/CodeSigning.java | 10 ++-------- .../hapsigntool/hap/provider/SignProvider.java | 1 - 4 files changed, 16 insertions(+), 16 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 681a754c..e6906c47 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 @@ -122,7 +122,7 @@ public class ElfHeader { */ 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)) { + if (read != ident.length || !isElfFile(ident)) { throw new ElfFormatException("Not a elf file"); } eiClass = ident[4]; @@ -201,4 +201,17 @@ public class ElfHeader { public short getEPhnum() { return ePhNum; } + + /** + * elf file start with [0x7F 0x45 0x4C 0x46] + * + * @param bytes byte array + * @return true if start with [0x7F 0x45 0x4C 0x46] + */ + public static boolean isElfFile(byte[] bytes) { + if (bytes == null || bytes.length != 4) { + return false; + } + return bytes[0] == 0x7F && bytes[1] == 0x45 && bytes[2] == 0x4C && bytes[3] == 0x46; + } } 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 f4199038..c7a674bb 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 @@ -51,12 +51,6 @@ public class FsVerityGenerator { private PageInfoExtension pageInfoExtension; - /** - * Constructor for FsVerityGenerator - */ - public FsVerityGenerator() { - } - /** * Constructor for FsVerityGenerator * 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 9afc9914..91f807fc 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 @@ -22,6 +22,7 @@ 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.elf.ElfHeader; import com.ohos.hapsigntool.codesigning.exception.CodeSignException; import com.ohos.hapsigntool.codesigning.exception.FsVerityDigestException; import com.ohos.hapsigntool.codesigning.fsverity.FsVerityDescriptor; @@ -335,7 +336,7 @@ public class CodeSigning { while ((libEntry = hnpInputStream.getNextEntry()) != null) { byte[] bytes = new byte[4]; hnpInputStream.read(bytes, 0, 4); - if (!isElfFile(bytes)) { + if (!ElfHeader.isElfFile(bytes)) { hnpInputStream.closeEntry(); continue; } @@ -391,13 +392,6 @@ public class CodeSigning { return false; } - private boolean isElfFile(byte[] bytes) { - if (bytes == null || bytes.length != 4) { - return false; - } - return bytes[0] == 0x7F && bytes[1] == 0x45 && bytes[2] == 0x4C && bytes[3] == 0x46; - } - /** * Sign specific entries in a hap * 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 39c80015..aefaf8da 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,7 +19,6 @@ 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; -- Gitee From df37d5c17255dc344e1fc04db0b12c5d155be12c Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Fri, 26 Jul 2024 11:18:25 +0800 Subject: [PATCH 08/28] clean code check Signed-off-by: wangzeyu --- .../codesigning/sign/CodeSigning.java | 2 +- .../codesigning/sign/PageInfoGenerator.java | 2 +- .../hap/provider/SignProvider.java | 1 + .../com/ohos/hapsigntool/zip/EntryType.java | 7 +- .../java/com/ohos/hapsigntool/zip/Zip.java | 12 ++- .../com/ohos/hapsigntool/zip/ZipEntry.java | 85 +++++++++++-------- .../ohos/hapsigntool/zip/ZipEntryData.java | 22 ++--- 7 files changed, 77 insertions(+), 54 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 91f807fc..17df8c90 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 @@ -220,7 +220,7 @@ public class CodeSigning { for (ZipEntry entry : zip.getZipEntries()) { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); EntryType type = entry.getZipEntryData().getType(); - if (EntryType.BitMap.equals(type) || EntryType.RunnableFile.equals(type)) { + 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 fa086c4d..2c131f96 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 @@ -81,7 +81,7 @@ public class PageInfoGenerator { throw new HapFormatException( String.format(Locale.ROOT, "Invalid entryDataOffset(%d), not a multiple of 4096", entryDataOffset)); } - if (EntryType.RunnableFile.equals(entry.getZipEntryData().getType())) { + if (EntryType.runnableFile.equals(entry.getZipEntryData().getType())) { runnableFileNames.put(zipEntryHeader.getFileName(), entryDataOffset); continue; } 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 aefaf8da..9fb59540 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 @@ -498,6 +498,7 @@ public abstract class SignProvider { * @param input file input * @param tmpOutput file tmpOutput * @param alignment alignment + * @param suffix suffix * @return zip zip * @throws IOException io error * @throws HapFormatException hap format error 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 index 46d44b13..bd190dc3 100644 --- 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 @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.ohos.hapsigntool.zip; /** @@ -20,7 +21,7 @@ package com.ohos.hapsigntool.zip; * @since 2024/06/25 */ public enum EntryType { - RunnableFile, - BitMap, - ResourceFile; + 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 4dd39574..fb2ef871 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 @@ -190,7 +190,7 @@ public class Zip { ZipEntryData zipEntryData = entry.getZipEntryData(); FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), fos); boolean isSuccess; - if (entry.getZipEntryData().getType() == EntryType.BitMap) { + if (entry.getZipEntryData().getType() == EntryType.bitMap) { ByteBuffer bf = ByteBuffer.wrap(entry.getZipEntryData().getData()); bf.order(ByteOrder.LITTLE_ENDIAN); isSuccess = FileUtils.writeByteToOutFile(bf.array(), fos); @@ -236,7 +236,7 @@ public class Zip { } int alignBytes; EntryType type = entry.getZipEntryData().getType(); - if (type == EntryType.RunnableFile || type == EntryType.BitMap) { + if (type == EntryType.runnableFile || type == EntryType.bitMap) { // .abc and .so file align 4096 byte. alignBytes = 4096; } else if (isFirstUnRunnableFile) { @@ -257,9 +257,15 @@ public class Zip { } } + /** + * add bit map entry + * + * @param data bitmap data + * @throws ZipException ZipException + */ public void addBitMap(byte[] data) throws ZipException { for (ZipEntry e : zipEntries) { - if (e.getZipEntryData().getType() == EntryType.BitMap) { + if (e.getZipEntryData().getType() == EntryType.bitMap) { e.getZipEntryData().setData(data); e.getZipEntryData().getZipEntryHeader().setUnCompressedSize(data.length); e.getZipEntryData().getZipEntryHeader().setCompressedSize(data.length); 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 03682ddd..7697d2bb 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 @@ -125,6 +125,9 @@ public class ZipEntry { this.fileEntryInCentralDirectory = centralDirectory; } + /** + * zip entry builder + */ public static class Builder { private short version = 10; @@ -189,46 +192,52 @@ public class ZipEntry { return this; } + /** + * build zip entry + * + * @return Zip Entry + * @throws ZipException ZipException + */ public ZipEntry build() throws ZipException { + long time = System.currentTimeMillis(); + CentralDirectory cd = addCenterDirectory(time); + ZipEntryHeader zipEntryHeader = addZipEntryHeader(time); + 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 entryData = new ZipEntryData(); + entryData.setData(data); + entryData.setZipEntryHeader(zipEntryHeader); ZipEntry entry = new ZipEntry(); - ZipEntryData zipEntryData = new ZipEntryData(); - zipEntryData.setData(data); + entry.setZipEntryData(entryData); + entryData.setType(EntryType.bitMap); + entry.setCentralDirectory(cd); + return entry; + } - ZipEntryHeader zipEntryHeader = new ZipEntryHeader(); + private CentralDirectory addCenterDirectory(long time) { 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); - - 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); 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); @@ -240,22 +249,28 @@ public class ZipEntry { cd.setExternalFile(0); cd.updateLength(); - zipEntryHeader.updateLength(); + return cd; + } - if (data == null) { - throw new ZipException("can not find entry data"); + private ZipEntryHeader addZipEntryHeader(long time) { + ZipEntryHeader zipEntryHeader = new ZipEntryHeader(); + zipEntryHeader.setVersion(version); + zipEntryHeader.setFlag(flag); + zipEntryHeader.setMethod(method); + zipEntryHeader.setLastTime((short) (time >> 32)); + zipEntryHeader.setLastDate((short) time); + zipEntryHeader.setCompressedSize(compressedSize); + zipEntryHeader.setUnCompressedSize(unCompressedSize); + zipEntryHeader.setFileName(fileName); + zipEntryHeader.setFileNameLength(fileName.length()); + if (extraData != null) { + zipEntryHeader.setExtraData(extraData); + zipEntryHeader.setExtraLength(extraData.length); + } else { + zipEntryHeader.setExtraLength(0); } - 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; + zipEntryHeader.updateLength(); + return zipEntryHeader; } } } \ 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 fc9327cb..18eb4df8 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 @@ -47,10 +47,6 @@ public class ZipEntryData { private long length; - public ZipEntryHeader getZipEntryHeader() { - return zipEntryHeader; - } - private EntryType type; private byte[] data; @@ -60,7 +56,7 @@ public class ZipEntryData { */ public void updateLength() { zipEntryHeader.updateLength(); - if (type == EntryType.BitMap) { + if (type == EntryType.bitMap) { length = zipEntryHeader.getLength() + data.length + (dataDescriptor == null ? 0 : 16); } else { length = zipEntryHeader.getLength() + fileSize + (dataDescriptor == null ? 0 : 16); @@ -102,16 +98,16 @@ public class ZipEntryData { ZipEntryData entry = new ZipEntryData(); entry.setFileOffset(offset); entry.setFileSize(fileSize); - byte[] data = FileUtils.readInputByLength(input, fileSize); + byte[] readData = 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; + entry.setType(EntryType.runnableFile); + } else if (FileUtils.BIT_MAP_FILENAME.equals(entryHeader.getFileName())) { + entry.setType(EntryType.bitMap); + entry.data = readData; } else { - entry.setType(EntryType.ResourceFile); + entry.setType(EntryType.resourceFile); } long entryLength = entryHeader.getLength() + fileSize; @@ -135,6 +131,10 @@ public class ZipEntryData { this.zipEntryHeader = zipEntryHeader; } + public ZipEntryHeader getZipEntryHeader() { + return zipEntryHeader; + } + public DataDescriptor getDataDescriptor() { return dataDescriptor; } -- Gitee From cf3e35908ec7fdda6b75881c283c9270e28033f9 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Fri, 26 Jul 2024 11:26:40 +0800 Subject: [PATCH 09/28] clean code check Signed-off-by: wangzeyu --- .../src/main/java/com/ohos/hapsigntool/zip/Zip.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 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 fb2ef871..f37ec36c 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 @@ -295,17 +295,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; -- Gitee From a6f231e047bc11442aeb5035fcd86b6f257fc3bf Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Fri, 26 Jul 2024 11:41:24 +0800 Subject: [PATCH 10/28] clean code Signed-off-by: zfeixiang --- .../java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e6906c47..90b1570f 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 @@ -209,7 +209,7 @@ public class ElfHeader { * @return true if start with [0x7F 0x45 0x4C 0x46] */ public static boolean isElfFile(byte[] bytes) { - if (bytes == null || bytes.length != 4) { + if (bytes == null || bytes.length < 4) { return false; } return bytes[0] == 0x7F && bytes[1] == 0x45 && bytes[2] == 0x4C && bytes[3] == 0x46; -- Gitee From 0765d84921698db8e6ea1a55e6c3f27f1d53ca81 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Fri, 26 Jul 2024 11:53:33 +0800 Subject: [PATCH 11/28] clean code check Signed-off-by: wangzeyu --- .../com/ohos/hapsigntool/codesigning/sign/CodeSigning.java | 4 +++- .../hapsigntool/codesigning/sign/PageInfoGenerator.java | 3 ++- .../src/main/java/com/ohos/hapsigntool/zip/Zip.java | 5 +++-- .../main/java/com/ohos/hapsigntool/zip/ZipEntryData.java | 6 ++---- 4 files changed, 10 insertions(+), 8 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 17df8c90..b36ca133 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 @@ -220,7 +220,9 @@ public class CodeSigning { for (ZipEntry entry : zip.getZipEntries()) { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); EntryType type = entry.getZipEntryData().getType(); - if (EntryType.bitMap.equals(type) || EntryType.runnableFile.equals(type)) { + short method = zipEntryHeader.getMethod(); + if (EntryType.bitMap.equals(type) || + (EntryType.runnableFile.equals(type) && method == Zip.FILE_UNCOMPRESS_METHOD_FLAG)) { 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 2c131f96..aa3d30e4 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 @@ -81,7 +81,8 @@ public class PageInfoGenerator { throw new HapFormatException( String.format(Locale.ROOT, "Invalid entryDataOffset(%d), not a multiple of 4096", entryDataOffset)); } - if (EntryType.runnableFile.equals(entry.getZipEntryData().getType())) { + if (EntryType.runnableFile.equals(entry.getZipEntryData().getType()) + && Zip.FILE_UNCOMPRESS_METHOD_FLAG == entry.getZipEntryData().getZipEntryHeader().getMethod()) { runnableFileNames.put(zipEntryHeader.getFileName(), entryDataOffset); continue; } 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 f37ec36c..97d1ed42 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 @@ -190,7 +190,7 @@ public class Zip { ZipEntryData zipEntryData = entry.getZipEntryData(); FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), fos); boolean isSuccess; - if (entry.getZipEntryData().getType() == EntryType.bitMap) { + if (entry.getZipEntryData().getData() != null) { ByteBuffer bf = ByteBuffer.wrap(entry.getZipEntryData().getData()); bf.order(ByteOrder.LITTLE_ENDIAN); isSuccess = FileUtils.writeByteToOutFile(bf.array(), fos); @@ -236,7 +236,8 @@ public class Zip { } int alignBytes; EntryType type = entry.getZipEntryData().getType(); - if (type == EntryType.runnableFile || type == EntryType.bitMap) { + if ((type == EntryType.runnableFile && method == FILE_UNCOMPRESS_METHOD_FLAG) || + type == EntryType.bitMap) { // .abc and .so file align 4096 byte. alignBytes = 4096; } else if (isFirstUnRunnableFile) { 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 18eb4df8..c17b98b8 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 @@ -98,14 +98,12 @@ public class ZipEntryData { ZipEntryData entry = new ZipEntryData(); entry.setFileOffset(offset); entry.setFileSize(fileSize); - byte[] readData = FileUtils.readInputByLength(input, fileSize); + input.skip(fileSize); - if (entryHeader.getMethod() == Zip.FILE_UNCOMPRESS_METHOD_FLAG - && FileUtils.isRunnableFile(entryHeader.getFileName())) { + if (FileUtils.isRunnableFile(entryHeader.getFileName())) { entry.setType(EntryType.runnableFile); } else if (FileUtils.BIT_MAP_FILENAME.equals(entryHeader.getFileName())) { entry.setType(EntryType.bitMap); - entry.data = readData; } else { entry.setType(EntryType.resourceFile); } -- Gitee From e776bb5c63e64833c96fbc2ef49c493421341d8e Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Fri, 26 Jul 2024 16:28:20 +0800 Subject: [PATCH 12/28] bitmap generator Signed-off-by: zfeixiang --- .../codesigning/sign/CodeSigning.java | 20 +++++++++------- .../codesigning/sign/PageInfoGenerator.java | 23 ------------------- 2 files changed, 12 insertions(+), 31 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 b36ca133..cc9414dd 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 @@ -182,7 +182,6 @@ 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); @@ -208,11 +207,13 @@ public class CodeSigning { return generated; } - private void createPageInfoExtension(Zip zip) { - long[] bitmapOffSize = PageInfoGenerator.getPageInfoFromZip(zip); - if (bitmapOffSize.length == 2) { - pageInfoExtension = new PageInfoExtension(bitmapOffSize[0], bitmapOffSize[1]); - } + private void createPageInfoExtension(ZipEntry entry) { + long bitmapOff = entry.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + + entry.getZipEntryData().getZipEntryHeader().getFileNameLength() + entry.getZipEntryData() + .getZipEntryHeader() + .getExtraLength(); + long bitmapSize = bitmapOff * 8; + pageInfoExtension = new PageInfoExtension(bitmapOff, bitmapSize); } private long computeDataSize(Zip zip) throws HapFormatException { @@ -221,8 +222,11 @@ public class CodeSigning { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); EntryType type = entry.getZipEntryData().getType(); short method = zipEntryHeader.getMethod(); - if (EntryType.bitMap.equals(type) || - (EntryType.runnableFile.equals(type) && method == Zip.FILE_UNCOMPRESS_METHOD_FLAG)) { + if ((EntryType.runnableFile.equals(type) && method == Zip.FILE_UNCOMPRESS_METHOD_FLAG)) { + continue; + } + if (EntryType.bitMap.equals(type)) { + createPageInfoExtension(entry); 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 aa3d30e4..001384fa 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 @@ -153,29 +153,6 @@ public class PageInfoGenerator { return buffer.array(); } - /** - * 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) { - String fileName = e.getCentralDirectory().getFileName(); - if (!FileUtils.BIT_MAP_FILENAME.equals(fileName)) { - continue; - } - long fileOffset = e.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + e.getZipEntryData() - .getZipEntryHeader() - .getFileNameLength() + e.getZipEntryData().getZipEntryHeader().getExtraLength(); - long fileSize = e.getCentralDirectory().getUnCompressedSize(); - long bitmapSize = fileSize * 8; - return new long[] {fileOffset, bitmapSize}; - } - return new long[0]; - } - static class ExcSegment { /** * abc or elf -- Gitee From efa272f88442b392a49cfc1e92f3d68de389ba49 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Fri, 26 Jul 2024 16:31:41 +0800 Subject: [PATCH 13/28] bitmap generator Signed-off-by: zfeixiang --- .../java/com/ohos/hapsigntool/hap/provider/SignProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9fb59540..b9f7cd76 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 @@ -507,7 +507,7 @@ public abstract class SignProvider { throws IOException, HapFormatException { Zip zip = new Zip(input); zip.alignment(alignment); - if ("hap".equals(suffix)) { + if (StringUtils.containsIgnoreCase(CodeSigning.SUPPORT_FILE_FORM, suffix)) { PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); byte[] bitMap = pageInfoGenerator.generateBitMap(); if (bitMap != null) { -- Gitee From d8244964270be6077cdcd571d663b1ec40c04b6d Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Fri, 26 Jul 2024 17:24:55 +0800 Subject: [PATCH 14/28] bitmap generator Signed-off-by: zfeixiang --- .../datastructure/PageInfoExtension.java | 8 ++++++++ .../hapsigntool/codesigning/sign/CodeSigning.java | 3 ++- .../codesigning/sign/PageInfoGenerator.java | 13 +++++-------- 3 files changed, 15 insertions(+), 9 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 4dae86b5..bbc5d699 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 @@ -19,6 +19,7 @@ import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.Locale; /** * Pages info extension is a type of Extension to store bitmap file's information, i.e. size and offset, ect. @@ -168,4 +169,11 @@ public class PageInfoExtension extends Extension { extension.setSignature(inSignature); return extension; } + + @Override + public String toString() { + return String.format(Locale.ROOT, + "PageInfoExtension: size[%d], mapOffset[%d], mapSize[%d], unitSize[%d], signSize[%d]", size(), + this.mapOffset, this.mapSize, this.unitSize, this.signSize); + } } 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 cc9414dd..64deb70e 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 @@ -212,7 +212,7 @@ public class CodeSigning { + entry.getZipEntryData().getZipEntryHeader().getFileNameLength() + entry.getZipEntryData() .getZipEntryHeader() .getExtraLength(); - long bitmapSize = bitmapOff * 8; + long bitmapSize = bitmapOff / CodeSignBlock.PAGE_SIZE_4K * PageInfoExtension.DEFAULT_UNIT_SIZE; pageInfoExtension = new PageInfoExtension(bitmapOff, bitmapSize); } @@ -466,6 +466,7 @@ public class CodeSigning { byte[] signatureV2 = generateSignature(fsVerityDigestV2, ownerID); pageInfoExtension.setSignature(signatureV2); signInfo.addExtension(pageInfoExtension); + LOGGER.debug(pageInfoExtension.toString()); } } 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 001384fa..23c1f469 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 @@ -15,6 +15,7 @@ package com.ohos.hapsigntool.codesigning.sign; +import com.ohos.hapsigntool.codesigning.datastructure.CodeSignBlock; import com.ohos.hapsigntool.codesigning.datastructure.PageInfoExtension; import com.ohos.hapsigntool.codesigning.elf.ElfFile; import com.ohos.hapsigntool.codesigning.elf.ElfProgramHeader; @@ -53,10 +54,6 @@ public class PageInfoGenerator { private static final byte ELF_M_CODE = 1; - private static final long PAGE_SIZE_4K = 4096L; - - private static final long PAGE_SIZE_1K = PAGE_SIZE_4K / PageInfoExtension.DEFAULT_UNIT_SIZE; - private static final Logger LOGGER = LogManager.getLogger(PageInfoGenerator.class); private long maxEntryDataOffset = 0L; @@ -77,7 +74,7 @@ public class PageInfoGenerator { ZipEntryHeader zipEntryHeader = entry.getZipEntryData().getZipEntryHeader(); long entryDataOffset = entry.getCentralDirectory().getOffset() + ZipEntryHeader.HEADER_LENGTH + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); - if (entryDataOffset % PAGE_SIZE_4K != 0) { + if (entryDataOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { throw new HapFormatException( String.format(Locale.ROOT, "Invalid entryDataOffset(%d), not a multiple of 4096", entryDataOffset)); } @@ -126,15 +123,15 @@ public class PageInfoGenerator { * @throws HapFormatException hap format error */ public byte[] generateBitMap() throws HapFormatException { - if (maxEntryDataOffset % PAGE_SIZE_4K != 0) { + if (maxEntryDataOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { throw new HapFormatException( String.format(Locale.ROOT, "Invalid maxEndOff(%d), not a multiple of 4096", maxEntryDataOffset)); } - int len = (int) (maxEntryDataOffset / PAGE_SIZE_1K); + int len = (int) (maxEntryDataOffset / CodeSignBlock.PAGE_SIZE_4K * PageInfoExtension.DEFAULT_UNIT_SIZE); BitSet bitmap = new BitSet(len); for (ExcSegment es : excSegmentList) { int begin = (int) (es.getStartOffset() >> 12) * PageInfoExtension.DEFAULT_UNIT_SIZE; - int end = (es.getEndOffset() % PAGE_SIZE_4K == 0) + int end = (es.getEndOffset() % CodeSignBlock.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) { -- Gitee From fe9459484cac4768ca345b928eccdfd0d89671c0 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Fri, 26 Jul 2024 17:52:50 +0800 Subject: [PATCH 15/28] bitmap generator Signed-off-by: zfeixiang --- .../datastructure/MerkleTreeExtension.java | 2 +- .../datastructure/PageInfoExtension.java | 4 ++-- .../codesigning/datastructure/SignInfo.java | 13 ++++++------- 3 files changed, 9 insertions(+), 10 deletions(-) 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 39840619..f46af4e9 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, Extension.EXTENSION_HEADER_SIZE + MERKLE_TREE_EXTENSION_DATA_SIZE); + super(MERKLE_TREE_INLINED, MERKLE_TREE_EXTENSION_DATA_SIZE); this.merkleTreeSize = merkleTreeSize; this.merkleTreeOffset = merkleTreeOffset; if (rootHash == 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 bbc5d699..7c2aecb8 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 @@ -83,7 +83,7 @@ public class PageInfoExtension extends Extension { * @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); + super(PAGE_INFO_INLINED, PAGE_INFO_EXTENSION_DATA_SIZE_WITHOUT_SIGN); this.mapOffset = mapOffset; this.mapSize = mapSize; unitSize = DEFAULT_UNIT_SIZE; @@ -95,7 +95,7 @@ public class PageInfoExtension extends Extension { this.signature = signature; this.zeroPadding = new byte[(SIGNATURE_ALIGNMENT - (signSize % SIGNATURE_ALIGNMENT)) % SIGNATURE_ALIGNMENT]; } - super.setSize(size()); + super.setSize(size() - Extension.EXTENSION_HEADER_SIZE); } public long getMapOffset() { 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 d146bf8f..ca2277f7 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 @@ -276,20 +276,19 @@ public class SignInfo { 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"); + if (extensionSize != (MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE)) { + throw new VerifyCodeSignException("Invalid MerkleTree extensionSize of SignInfo"); } - byte[] merkleTreeExtension = new byte[MerkleTreeExtension.MERKLE_TREE_EXTENSION_DATA_SIZE]; + byte[] merkleTreeExtension = new byte[extensionSize]; 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"); + if (extensionSize < (PageInfoExtension.PAGE_INFO_EXTENSION_DATA_SIZE_WITHOUT_SIGN)) { + throw new VerifyCodeSignException("Invalid PageInfo extensionSize of SignInfo"); } - byte[] pageInfoExtension = new byte[extensionSize - Extension.EXTENSION_HEADER_SIZE]; + byte[] pageInfoExtension = new byte[extensionSize]; bf.get(pageInfoExtension); inExtensionList.add(PageInfoExtension.fromByteArray(pageInfoExtension)); } else { -- Gitee From 82715f134eeffb41821b1649d4d031abd0205dce Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Fri, 26 Jul 2024 12:41:37 +0000 Subject: [PATCH 16/28] update hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java. Signed-off-by: wangzeyu --- .../src/main/java/com/ohos/hapsigntool/zip/ZipEntryData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c17b98b8..f32cd5ef 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 @@ -56,7 +56,7 @@ public class ZipEntryData { */ public void updateLength() { zipEntryHeader.updateLength(); - if (type == EntryType.bitMap) { + if (data != null) { length = zipEntryHeader.getLength() + data.length + (dataDescriptor == null ? 0 : 16); } else { length = zipEntryHeader.getLength() + fileSize + (dataDescriptor == null ? 0 : 16); -- Gitee From b6e97c5fa0c17dd789ca31541b28dc6fd2d0f2f0 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Fri, 26 Jul 2024 22:47:33 +0800 Subject: [PATCH 17/28] bitmap generator Signed-off-by: zfeixiang --- .../com/ohos/hapsigntoolcmd/CmdUnitTest.java | 2 +- .../datastructure/HapInfoSegment.java | 3 +- .../datastructure/MerkleTreeExtension.java | 5 +-- .../datastructure/PageInfoExtension.java | 3 +- .../hapsigntool/codesigning/elf/ElfFile.java | 12 +++++++ .../codesigning/elf/ElfHeader.java | 16 +++++++-- .../fsverity/FsVerityDescriptor.java | 3 +- .../codesigning/sign/CodeSigning.java | 3 +- .../codesigning/sign/PageInfoGenerator.java | 20 ++++++----- .../codesigning/utils/NumberUtils.java | 33 +++++++++++++++++++ .../hap/provider/SignProvider.java | 14 ++++---- 11 files changed, 89 insertions(+), 25 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/utils/NumberUtils.java diff --git a/hapsigntool/hap_sign_tool/src/test/java/com/ohos/hapsigntoolcmd/CmdUnitTest.java b/hapsigntool/hap_sign_tool/src/test/java/com/ohos/hapsigntoolcmd/CmdUnitTest.java index b5f568ce..26854416 100644 --- a/hapsigntool/hap_sign_tool/src/test/java/com/ohos/hapsigntoolcmd/CmdUnitTest.java +++ b/hapsigntool/hap_sign_tool/src/test/java/com/ohos/hapsigntoolcmd/CmdUnitTest.java @@ -958,7 +958,7 @@ public class CmdUnitTest { CMD_SIGN_ALG, CMD_SHA_256_WITH_ECDSA, CMD_KEY_STORE_FILE, CMD_KEY_APP_STORE_PATH, CMD_KEY_STORE_RIGHTS, CMD_RIGHTS_123456, - CMD_IN_FILE, unsignedHap, + CMD_IN_FILE, signedHap, CMD_OUT_FILE, signedHap }); assertTrue(result); 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 4b8be585..b25d4eb6 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 @@ -16,6 +16,7 @@ package com.ohos.hapsigntool.codesigning.datastructure; import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; +import com.ohos.hapsigntool.codesigning.utils.NumberUtils; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -116,7 +117,7 @@ public class HapInfoSegment { byte[] hapSignInfoByteArray = new byte[bytes.length - MAGIC_NUM_BYTES]; bf.get(hapSignInfoByteArray); SignInfo inHapSignInfo = SignInfo.fromByteArray(hapSignInfoByteArray); - if (inHapSignInfo.getDataSize() % CodeSignBlock.PAGE_SIZE_4K != 0) { + if (!NumberUtils.isMultiple4K(inHapSignInfo.getDataSize())) { throw new VerifyCodeSignException( String.format(Locale.ROOT, "Invalid dataSize number of HapInfoSegment, not a multiple of 4096: %d", inHapSignInfo.getDataSize())); 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 f46af4e9..96bc17ee 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 @@ -16,6 +16,7 @@ package com.ohos.hapsigntool.codesigning.datastructure; import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; +import com.ohos.hapsigntool.codesigning.utils.NumberUtils; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -118,11 +119,11 @@ public class MerkleTreeExtension extends Extension { bf.put(bytes); bf.rewind(); long inMerkleTreeSize = bf.getLong(); - if (inMerkleTreeSize % CodeSignBlock.PAGE_SIZE_4K != 0) { + if (!NumberUtils.isMultiple4K(inMerkleTreeSize)) { throw new VerifyCodeSignException("merkleTreeSize is not a multiple of 4096"); } long inMerkleTreeOffset = bf.getLong(); - if (inMerkleTreeOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { + if (!NumberUtils.isMultiple4K(inMerkleTreeOffset)) { throw new VerifyCodeSignException("merkleTreeOffset is not a aligned to 4096"); } byte[] inRootHash = new byte[ROOT_HASH_SIZE]; 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 7c2aecb8..377de03c 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 @@ -16,6 +16,7 @@ package com.ohos.hapsigntool.codesigning.datastructure; import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; +import com.ohos.hapsigntool.codesigning.utils.NumberUtils; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -152,7 +153,7 @@ public class PageInfoExtension extends Extension { bf.put(bytes); bf.rewind(); long inMapOffset = bf.getLong(); - if (inMapOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { + if (!NumberUtils.isMultiple4K(inMapOffset)) { throw new VerifyCodeSignException("mapOffset is not a multiple of 4096"); } long inMapSize = bf.getLong(); 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 e84d446c..9e600a20 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 @@ -42,6 +42,9 @@ public class ElfFile { */ public ElfFile(InputStream is) throws IOException, ElfFormatException { elfHeader = new ElfHeader(is); + if (!isElfFile()) { + return; + } byte eiClass = elfHeader.getEiClass(); byte eiData = elfHeader.getEiData(); short ePhnum = elfHeader.getEPhnum(); @@ -65,4 +68,13 @@ public class ElfFile { public List filterExecPHeaders() { return programHeaderList.stream().filter(phdr -> (phdr.getPFlags() & 1) == 1).collect(Collectors.toList()); } + + /** + * return true if magic number is correct + * + * @return true if magic number is correct + */ + public boolean isElfFile() { + return elfHeader.isElfFile(); + } } 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 90b1570f..12270c4e 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 @@ -122,8 +122,8 @@ public class ElfHeader { */ public ElfHeader(InputStream is) throws IOException, ElfFormatException { int read = is.read(ident); - if (read != ident.length || !isElfFile(ident)) { - throw new ElfFormatException("Not a elf file"); + if (read != ident.length || !isElfFile()) { + return; } eiClass = ident[4]; eiData = ident[5]; @@ -214,4 +214,16 @@ public class ElfHeader { } return bytes[0] == 0x7F && bytes[1] == 0x45 && bytes[2] == 0x4C && bytes[3] == 0x46; } + + /** + * return true if magic number is correct + * + * @return true if magic number is correct + */ + public boolean isElfFile() { + if (ident == null || ident.length < 4) { + return false; + } + return ident[0] == 0x7F && ident[1] == 0x45 && ident[2] == 0x4C && ident[3] == 0x46; + } } 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 2d3d044e..da6f8ec1 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 @@ -17,6 +17,7 @@ package com.ohos.hapsigntool.codesigning.fsverity; import com.ohos.hapsigntool.codesigning.exception.FsVerityDigestException; import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; +import com.ohos.hapsigntool.codesigning.utils.NumberUtils; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -173,7 +174,7 @@ public class FsVerityDescriptor { int inFlags = bf.getInt(); bf.getInt(); long inTreeOffset = bf.getLong(); - if (inTreeOffset % PAGE_SIZE_4K != 0) { + if (!NumberUtils.isMultiple4K(inTreeOffset)) { throw new VerifyCodeSignException("Invalid merkle tree offset of ElfSignBlock"); } bf.get(new byte[FsVerityDescriptor.RESERVED_SIZE_AFTER_TREE_OFFSET]); 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 64deb70e..e9b2b509 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 @@ -29,6 +29,7 @@ import com.ohos.hapsigntool.codesigning.fsverity.FsVerityDescriptor; import com.ohos.hapsigntool.codesigning.fsverity.FsVerityDescriptorWithSign; import com.ohos.hapsigntool.codesigning.fsverity.FsVerityGenerator; import com.ohos.hapsigntool.codesigning.utils.HapUtils; +import com.ohos.hapsigntool.codesigning.utils.NumberUtils; import com.ohos.hapsigntool.entity.Pair; import com.ohos.hapsigntool.error.HapFormatException; import com.ohos.hapsigntool.error.ProfileException; @@ -238,7 +239,7 @@ public class CodeSigning { + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); break; } - if ((dataSize % CodeSignBlock.PAGE_SIZE_4K) != 0) { + if (!NumberUtils.isMultiple4K(dataSize)) { throw new HapFormatException( String.format(Locale.ROOT, "Invalid dataSize(%d), not a multiple of 4096", dataSize)); } 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 23c1f469..d376bad1 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.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.codesigning.utils.NumberUtils; import com.ohos.hapsigntool.error.HapFormatException; import com.ohos.hapsigntool.utils.FileUtils; import com.ohos.hapsigntool.zip.EntryType; @@ -67,14 +68,14 @@ public class PageInfoGenerator { * @throws IOException io error * @throws HapFormatException hap file format error */ - public PageInfoGenerator(Zip zip) throws IOException, HapFormatException { + public PageInfoGenerator(Zip zip) throws IOException, HapFormatException, ElfFormatException { Map runnableFileNames = 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 % CodeSignBlock.PAGE_SIZE_4K != 0) { + if (!NumberUtils.isMultiple4K(entryDataOffset)) { throw new HapFormatException( String.format(Locale.ROOT, "Invalid entryDataOffset(%d), not a multiple of 4096", entryDataOffset)); } @@ -94,7 +95,8 @@ public class PageInfoGenerator { } } - private void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) throws IOException { + private void libExecSegment(JarFile hap, String libFileName, long entryDataOffset) + throws IOException, ElfFormatException { JarEntry libEntry = hap.getJarEntry(libFileName); if (libFileName.endsWith(FileUtils.ABC_FILE_SUFFIX)) { long size = libEntry.getSize(); @@ -102,6 +104,10 @@ public class PageInfoGenerator { } else { try (InputStream stream = hap.getInputStream(libEntry)) { ElfFile elfFile = new ElfFile(stream); + if (!elfFile.isElfFile()) { + LOGGER.info("{} not ELF file", libFileName); + return; + } List elfPHeaders = elfFile.filterExecPHeaders(); for (ElfProgramHeader programHeader : elfPHeaders) { long pOffset = programHeader.getPOffset(); @@ -110,8 +116,6 @@ public class PageInfoGenerator { long endoff = off + pFilesz; excSegmentList.add(new ExcSegment(ELF_M_CODE, libFileName, off, endoff)); } - } catch (ElfFormatException e) { - LOGGER.info(libFileName + " error : " + e.getMessage()); } } } @@ -123,7 +127,7 @@ public class PageInfoGenerator { * @throws HapFormatException hap format error */ public byte[] generateBitMap() throws HapFormatException { - if (maxEntryDataOffset % CodeSignBlock.PAGE_SIZE_4K != 0) { + if (!NumberUtils.isMultiple4K(maxEntryDataOffset)) { throw new HapFormatException( String.format(Locale.ROOT, "Invalid maxEndOff(%d), not a multiple of 4096", maxEntryDataOffset)); } @@ -131,10 +135,10 @@ public class PageInfoGenerator { BitSet bitmap = new BitSet(len); for (ExcSegment es : excSegmentList) { int begin = (int) (es.getStartOffset() >> 12) * PageInfoExtension.DEFAULT_UNIT_SIZE; - int end = (es.getEndOffset() % CodeSignBlock.PAGE_SIZE_4K == 0) + int end = (NumberUtils.isMultiple4K(es.getEndOffset())) ? (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) { + for (int i = begin; i < end; i = i + PageInfoExtension.DEFAULT_UNIT_SIZE) { if ((ELF_M_CODE == es.getType())) { bitmap.set(i); } else { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/utils/NumberUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/utils/NumberUtils.java new file mode 100644 index 00000000..47f91d72 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/utils/NumberUtils.java @@ -0,0 +1,33 @@ +/* + * 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.utils; + +/** + * InputStream util class + * + * @since 2024/07/01 + */ +public class NumberUtils { + /** + * Check whether number is multiple of 4096 + * + * @param num check number + * @return true if l is multiple of 4096 + */ + public static boolean isMultiple4K(long num) { + return (num & 0xfff) == 0; + } +} 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 b9f7cd76..dfd6f018 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,7 @@ 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; @@ -329,12 +330,8 @@ public abstract class SignProvider { File input = new File(signParams.get(ParamConstants.PARAM_BASIC_INPUT_FILE)); output = new File(signParams.get(ParamConstants.PARAM_BASIC_OUTPUT_FILE)); String suffix = getFileSuffix(input); - if (input.getCanonicalPath().equals(output.getCanonicalPath())) { - tmpOutput = File.createTempFile("signedHap", "." + suffix); - isPathOverlap = true; - } else { - tmpOutput = output; - } + isPathOverlap = input.getCanonicalPath().equals(output.getCanonicalPath()); + tmpOutput = isPathOverlap ? File.createTempFile("signedHap", "." + suffix) : output; // copy file and Alignment int alignment = Integer.parseInt(signParams.get(ParamConstants.PARAM_BASIC_ALIGNMENT)); Zip zip = copyFileAndAlignment(input, tmpOutput, alignment, suffix); @@ -365,7 +362,8 @@ public abstract class SignProvider { isRet = true; } } catch (FsVerityDigestException | InvalidKeyException | HapFormatException | MissingParamsException -|InvalidParamsException |ProfileException |NumberFormatException |CustomException |IOException |CodeSignException e) { + | InvalidParamsException | ProfileException | NumberFormatException | CustomException | IOException + | CodeSignException | ElfFormatException e) { printErrorLogWithoutStack(e); } catch (SignatureException e) { printErrorLog(e); @@ -504,7 +502,7 @@ public abstract class SignProvider { * @throws HapFormatException hap format error */ private Zip copyFileAndAlignment(File input, File tmpOutput, int alignment, String suffix) - throws IOException, HapFormatException { + throws IOException, HapFormatException, ElfFormatException { Zip zip = new Zip(input); zip.alignment(alignment); if (StringUtils.containsIgnoreCase(CodeSigning.SUPPORT_FILE_FORM, suffix)) { -- Gitee From 4ed9db620cb8927b907c0636e817f023d70b7033 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 27 Jul 2024 10:36:36 +0800 Subject: [PATCH 18/28] modify elf header Signed-off-by: zfeixiang --- .../hapsigntool/codesigning/elf/ElfHeader.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 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 12270c4e..f5ccefc1 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,6 +33,8 @@ public class ElfHeader { */ private byte[] ident = new byte[ElfDefine.EI_NIDENT_LEN]; + private boolean elfFile; + /** * 32-bit or 64-bit file */ @@ -122,7 +124,8 @@ public class ElfHeader { */ public ElfHeader(InputStream is) throws IOException, ElfFormatException { int read = is.read(ident); - if (read != ident.length || !isElfFile()) { + elfFile = isElfFile(ident); + if (read != ident.length || !elfFile) { return; } eiClass = ident[4]; @@ -166,16 +169,10 @@ public class ElfHeader { eEntry = byteBuffer.getInt() & 0xFFFFFFFFL; ePhOff = byteBuffer.getInt() & 0xFFFFFFFFL; eShOff = byteBuffer.getInt() & 0xFFFFFFFFL; - if (ePhOff != ElfDefine.ELF_HEADER_32_LEN) { - 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 Program header table file offset is incorrect"); - } } eFlags = byteBuffer.getInt(); eEhSize = byteBuffer.getShort(); @@ -221,9 +218,6 @@ public class ElfHeader { * @return true if magic number is correct */ public boolean isElfFile() { - if (ident == null || ident.length < 4) { - return false; - } - return ident[0] == 0x7F && ident[1] == 0x45 && ident[2] == 0x4C && ident[3] == 0x46; + return elfFile; } } -- Gitee From 96f4150a70991d5bb9d04788994c7cb2abc4a366 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 27 Jul 2024 11:31:10 +0800 Subject: [PATCH 19/28] code check Signed-off-by: zfeixiang --- .../codesigning/datastructure/HapInfoSegment.java | 7 ++++++- .../hapsigntool/codesigning/datastructure/SignInfo.java | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) 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 b25d4eb6..2892df03 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 @@ -18,6 +18,9 @@ package com.ohos.hapsigntool.codesigning.datastructure; import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; import com.ohos.hapsigntool.codesigning.utils.NumberUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Locale; @@ -45,6 +48,8 @@ public class HapInfoSegment { private SignInfo hapSignInfo; + private static final Logger LOGGER = LogManager.getLogger(HapInfoSegment.class); + /** * Default constructor of HapInfoSegment */ @@ -123,7 +128,7 @@ public class HapInfoSegment { inHapSignInfo.getDataSize())); } if (inHapSignInfo.getExtensionNum() > SignInfo.MAX_EXTENSION_NUM) { - throw new VerifyCodeSignException("Invalid extensionNum of HapInfoSegment"); + LOGGER.info("Invalid extensionNum {} of HapInfoSegment", inHapSignInfo.getExtensionNum()); } if (inHapSignInfo.getExtensionByType(MerkleTreeExtension.MERKLE_TREE_INLINED) == null) { throw new VerifyCodeSignException("No merkle tree extension is found in HapInfoSegment"); 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 ca2277f7..cecdeff9 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 @@ -17,6 +17,9 @@ package com.ohos.hapsigntool.codesigning.datastructure; import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; @@ -90,6 +93,8 @@ public class SignInfo { // temporary, use list instead private List extensionList = new ArrayList<>(); + private static final Logger LOGGER = LogManager.getLogger(SignInfo.class); + /** * Constructor for SignInfo * @@ -242,7 +247,7 @@ public class SignInfo { bf.get(inSalt); int inExtensionNum = bf.getInt(); if (inExtensionNum < 0 || inExtensionNum > MAX_EXTENSION_NUM) { - throw new VerifyCodeSignException("Invalid extensionNum of SignInfo"); + LOGGER.info("Invalid extensionNum {} of SignInfo", inExtensionNum); } int inExtensionOffset = bf.getInt(); if (inExtensionOffset < 0 || inExtensionOffset % 4 != 0) { @@ -292,7 +297,7 @@ public class SignInfo { bf.get(pageInfoExtension); inExtensionList.add(PageInfoExtension.fromByteArray(pageInfoExtension)); } else { - throw new VerifyCodeSignException("Invalid extensionType of SignInfo"); + LOGGER.info("Invalid extensionType {} of SignInfo", extensionType); } } return inExtensionList; -- Gitee From b18d01b83ec033c19c2cbd82e9936a1cea196c3d Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 27 Jul 2024 14:10:38 +0800 Subject: [PATCH 20/28] code check Signed-off-by: zfeixiang --- .../codesigning/datastructure/HapInfoSegment.java | 4 ++-- .../hapsigntool/codesigning/datastructure/SignInfo.java | 4 ++-- .../com/ohos/hapsigntool/codesigning/elf/ElfFile.java | 2 +- .../com/ohos/hapsigntool/codesigning/elf/ElfHeader.java | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) 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 2892df03..fc4b5835 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 @@ -37,6 +37,8 @@ import java.util.Locale; * @since 2023/09/08 */ public class HapInfoSegment { + private static final Logger LOGGER = LogManager.getLogger(HapInfoSegment.class); + private static final int MAGIC_NUM_BYTES = 4; /** @@ -48,8 +50,6 @@ public class HapInfoSegment { private SignInfo hapSignInfo; - private static final Logger LOGGER = LogManager.getLogger(HapInfoSegment.class); - /** * Default constructor of HapInfoSegment */ 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 cecdeff9..03c2e6f1 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 @@ -63,6 +63,8 @@ public class SignInfo { */ public static final int MAX_EXTENSION_NUM = 2; + private static final Logger LOGGER = LogManager.getLogger(SignInfo.class); + /** * sign info structure without signature in bytes, refer to toByteArray() method */ @@ -93,8 +95,6 @@ public class SignInfo { // temporary, use list instead private List extensionList = new ArrayList<>(); - private static final Logger LOGGER = LogManager.getLogger(SignInfo.class); - /** * Constructor for SignInfo * 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 9e600a20..2b473008 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 @@ -74,7 +74,7 @@ public class ElfFile { * * @return true if magic number is correct */ - public boolean isElfFile() { + public final boolean isElfFile() { return elfHeader.isElfFile(); } } 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 f5ccefc1..4bf59e14 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,7 +33,7 @@ public class ElfHeader { */ private byte[] ident = new byte[ElfDefine.EI_NIDENT_LEN]; - private boolean elfFile; + private boolean isElfFile; /** * 32-bit or 64-bit file @@ -124,8 +124,8 @@ public class ElfHeader { */ public ElfHeader(InputStream is) throws IOException, ElfFormatException { int read = is.read(ident); - elfFile = isElfFile(ident); - if (read != ident.length || !elfFile) { + isElfFile = isElfFile(ident); + if (read != ident.length || !isElfFile) { return; } eiClass = ident[4]; @@ -218,6 +218,6 @@ public class ElfHeader { * @return true if magic number is correct */ public boolean isElfFile() { - return elfFile; + return isElfFile; } } -- Gitee From 01bd460b0aa4a3f49835742329a289efceae2925 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 27 Jul 2024 15:13:46 +0800 Subject: [PATCH 21/28] code check Signed-off-by: zfeixiang --- .../codesigning/datastructure/HapInfoSegment.java | 2 +- .../ohos/hapsigntool/codesigning/elf/ElfFile.java | 4 ++-- .../ohos/hapsigntool/codesigning/elf/ElfHeader.java | 13 +++++++------ .../codesigning/elf/ElfProgramHeader.java | 7 ++++--- 4 files changed, 14 insertions(+), 12 deletions(-) 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 fc4b5835..ff5ef999 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 @@ -128,7 +128,7 @@ public class HapInfoSegment { inHapSignInfo.getDataSize())); } if (inHapSignInfo.getExtensionNum() > SignInfo.MAX_EXTENSION_NUM) { - LOGGER.info("Invalid extensionNum {} of HapInfoSegment", inHapSignInfo.getExtensionNum()); + LOGGER.info("Maybe the tool is out-of-date, extensionNum {}", inHapSignInfo.getExtensionNum()); } if (inHapSignInfo.getExtensionByType(MerkleTreeExtension.MERKLE_TREE_INLINED) == null) { throw new VerifyCodeSignException("No merkle tree extension is found in HapInfoSegment"); 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 2b473008..78f5c396 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 @@ -47,14 +47,14 @@ public class ElfFile { } byte eiClass = elfHeader.getEiClass(); byte eiData = elfHeader.getEiData(); - short ePhnum = elfHeader.getEPhnum(); + int 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++) { + for (int i = 0; i < ePhnum; i++) { ElfProgramHeader pHeader = new ElfProgramHeader(is, eiClass, eiData); programHeaderList.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 4bf59e14..28c31985 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 @@ -16,6 +16,7 @@ package com.ohos.hapsigntool.codesigning.elf; import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; +import com.ohos.hapsigntool.zip.UnsignedDecimalUtil; import java.io.IOException; import java.io.InputStream; @@ -98,7 +99,7 @@ public class ElfHeader { /** * Program header table entry count */ - private short ePhNum; + private int ePhNum; /** * Section header table entry size @@ -166,9 +167,9 @@ public class ElfHeader { eVersion = byteBuffer.getInt(); if (eiClass == ElfDefine.ELF_32_CLASS) { - eEntry = byteBuffer.getInt() & 0xFFFFFFFFL; - ePhOff = byteBuffer.getInt() & 0xFFFFFFFFL; - eShOff = byteBuffer.getInt() & 0xFFFFFFFFL; + eEntry = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); + ePhOff = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); + eShOff = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); } else { eEntry = byteBuffer.getLong(); ePhOff = byteBuffer.getLong(); @@ -177,7 +178,7 @@ public class ElfHeader { eFlags = byteBuffer.getInt(); eEhSize = byteBuffer.getShort(); ePhEntSize = byteBuffer.getShort(); - ePhNum = byteBuffer.getShort(); + ePhNum = UnsignedDecimalUtil.getUnsignedShort(byteBuffer); eShEntSize = byteBuffer.getShort(); eShNum = byteBuffer.getShort(); eShStrndx = byteBuffer.getShort(); @@ -195,7 +196,7 @@ public class ElfHeader { return ePhOff; } - public short getEPhnum() { + public int getEPhnum() { return ePhNum; } 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 c1b3ffa7..91d2a335 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 @@ -16,6 +16,7 @@ package com.ohos.hapsigntool.codesigning.elf; import com.ohos.hapsigntool.codesigning.exception.ElfFormatException; +import com.ohos.hapsigntool.zip.UnsignedDecimalUtil; import java.io.IOException; import java.io.InputStream; @@ -95,9 +96,9 @@ public class ElfProgramHeader { ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); byteBuffer.order(bo); pType = byteBuffer.getInt(); - pOffset = byteBuffer.getInt() & 0xFFFFFFFFL; - pVaddr = byteBuffer.getInt() & 0xFFFFFFFFL; - pPaddr = byteBuffer.getInt() & 0xFFFFFFFFL; + pOffset = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); + pVaddr = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); + pPaddr = UnsignedDecimalUtil.getUnsignedInt(byteBuffer); pFilesz = byteBuffer.getInt(); pMemsz = byteBuffer.getInt(); pFlags = byteBuffer.getInt(); -- Gitee From f5b03b1d78054575d13d7874bd764105f073ba00 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 27 Jul 2024 19:09:25 +0800 Subject: [PATCH 22/28] bitmap time Signed-off-by: wangzeyu --- .../com/ohos/hapsigntool/zip/ZipEntry.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) 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 7697d2bb..fc2a0d7f 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.Calendar; import java.util.zip.CRC32; /** @@ -199,7 +200,10 @@ public class ZipEntry { * @throws ZipException ZipException */ public ZipEntry build() throws ZipException { - long time = System.currentTimeMillis(); + Calendar calendar = Calendar.getInstance(); + int time = (calendar.get(Calendar.YEAR) - 80 << 25) | (calendar.get(Calendar.MONTH) + 1) << 21 | + calendar.get(Calendar.DAY_OF_MONTH) << 16 | calendar.get(Calendar.HOUR_OF_DAY) << 11 | + calendar.get(Calendar.MINUTE) << 5 | calendar.get(Calendar.SECOND) >> 1; CentralDirectory cd = addCenterDirectory(time); ZipEntryHeader zipEntryHeader = addZipEntryHeader(time); if (data == null) { @@ -221,14 +225,14 @@ public class ZipEntry { return entry; } - private CentralDirectory addCenterDirectory(long time) { + private CentralDirectory addCenterDirectory(int time) { CentralDirectory cd = new CentralDirectory(); cd.setVersion(version); cd.setVersionExtra(version); cd.setFlag(flag); cd.setMethod(method); - cd.setLastTime((short) (time >> 32)); - cd.setLastDate((short) time); + cd.setLastTime((short) time); + cd.setLastDate((short) (time >> 16)); cd.setCompressedSize(compressedSize); cd.setUnCompressedSize(unCompressedSize); cd.setFileName(fileName); @@ -252,13 +256,13 @@ public class ZipEntry { return cd; } - private ZipEntryHeader addZipEntryHeader(long time) { + private ZipEntryHeader addZipEntryHeader(int time) { ZipEntryHeader zipEntryHeader = new ZipEntryHeader(); zipEntryHeader.setVersion(version); zipEntryHeader.setFlag(flag); zipEntryHeader.setMethod(method); - zipEntryHeader.setLastTime((short) (time >> 32)); - zipEntryHeader.setLastDate((short) time); + zipEntryHeader.setLastTime((short) time); + zipEntryHeader.setLastDate((short) (time >> 16)); zipEntryHeader.setCompressedSize(compressedSize); zipEntryHeader.setUnCompressedSize(unCompressedSize); zipEntryHeader.setFileName(fileName); -- Gitee From ac8a8cded2d4f77a54f3084634ee76e116f2ab85 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 27 Jul 2024 19:13:29 +0800 Subject: [PATCH 23/28] code check Signed-off-by: zfeixiang --- .../com/ohos/hapsigntool/codesigning/utils/NumberUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/utils/NumberUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/utils/NumberUtils.java index 47f91d72..ab62c214 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/utils/NumberUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/codesigning/utils/NumberUtils.java @@ -28,6 +28,6 @@ public class NumberUtils { * @return true if l is multiple of 4096 */ public static boolean isMultiple4K(long num) { - return (num & 0xfff) == 0; + return (num & 0xfffL) == 0; } } -- Gitee From d23eeb2f7f514a61bc53bdc7653b4797f3278abf Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 27 Jul 2024 19:17:56 +0800 Subject: [PATCH 24/28] code check Signed-off-by: zfeixiang --- .../java/com/ohos/hapsigntool/codesigning/elf/ElfHeader.java | 3 --- 1 file changed, 3 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 28c31985..3d246d46 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 @@ -132,9 +132,6 @@ public class ElfHeader { eiClass = ident[4]; eiData = ident[5]; eiVersion = ident[6]; - if (eiVersion < 1) { - throw new ElfFormatException("ELF eiVersion is incorrect"); - } int len; if (eiClass == ElfDefine.ELF_32_CLASS) { len = ElfDefine.ELF_HEADER_32_LEN - ElfDefine.EI_NIDENT_LEN; -- Gitee From 3855982a5a517d79e5331c8dfb439cb4238a37f3 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 27 Jul 2024 19:23:33 +0800 Subject: [PATCH 25/28] bitmap time Signed-off-by: wangzeyu --- .../java/com/ohos/hapsigntool/hap/provider/SignProvider.java | 2 +- .../src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java | 5 +++-- 2 files changed, 4 insertions(+), 3 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 dfd6f018..7413b759 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 @@ -508,7 +508,7 @@ public abstract class SignProvider { if (StringUtils.containsIgnoreCase(CodeSigning.SUPPORT_FILE_FORM, suffix)) { PageInfoGenerator pageInfoGenerator = new PageInfoGenerator(zip); byte[] bitMap = pageInfoGenerator.generateBitMap(); - if (bitMap != null) { + if (bitMap != null && bitMap.length > 0) { zip.addBitMap(bitMap); zip.alignment(alignment); } 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 fc2a0d7f..e4a66513 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 @@ -201,9 +201,10 @@ public class ZipEntry { */ public ZipEntry build() throws ZipException { Calendar calendar = Calendar.getInstance(); - int time = (calendar.get(Calendar.YEAR) - 80 << 25) | (calendar.get(Calendar.MONTH) + 1) << 21 | + int time = (calendar.get(Calendar.YEAR) - 60) << 25 | (calendar.get(Calendar.MONTH) + 1) << 21 | calendar.get(Calendar.DAY_OF_MONTH) << 16 | calendar.get(Calendar.HOUR_OF_DAY) << 11 | - calendar.get(Calendar.MINUTE) << 5 | calendar.get(Calendar.SECOND) >> 1; + calendar.get(Calendar.MINUTE) << 5 | calendar.get(Calendar.SECOND) >> 1 + + ((calendar.getTimeInMillis() % 2000) << 32); CentralDirectory cd = addCenterDirectory(time); ZipEntryHeader zipEntryHeader = addZipEntryHeader(time); if (data == null) { -- Gitee From 78526229b23e38865600104ecb0df96269f446eb Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 27 Jul 2024 19:29:21 +0800 Subject: [PATCH 26/28] bitmap time Signed-off-by: wangzeyu --- .../src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 e4a66513..4402db26 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 @@ -201,10 +201,10 @@ public class ZipEntry { */ public ZipEntry build() throws ZipException { Calendar calendar = Calendar.getInstance(); - int time = (calendar.get(Calendar.YEAR) - 60) << 25 | (calendar.get(Calendar.MONTH) + 1) << 21 | - calendar.get(Calendar.DAY_OF_MONTH) << 16 | calendar.get(Calendar.HOUR_OF_DAY) << 11 | - calendar.get(Calendar.MINUTE) << 5 | calendar.get(Calendar.SECOND) >> 1 + - ((calendar.getTimeInMillis() % 2000) << 32); + int time = (calendar.get(Calendar.YEAR) - 60) << 25 | (calendar.get(Calendar.MONTH) + 1) << 21 + | calendar.get(Calendar.DAY_OF_MONTH) << 16 | calendar.get(Calendar.HOUR_OF_DAY) << 11 + | calendar.get(Calendar.MINUTE) << 5 | calendar.get(Calendar.SECOND) >> 1 + + ((calendar.getTimeInMillis() % 2000) << 32); CentralDirectory cd = addCenterDirectory(time); ZipEntryHeader zipEntryHeader = addZipEntryHeader(time); if (data == null) { -- Gitee From 887ad38dfccd839a72f0a07856f089c0002d25e0 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 27 Jul 2024 19:55:39 +0800 Subject: [PATCH 27/28] bitmap time Signed-off-by: wangzeyu --- .../src/main/java/com/ohos/hapsigntool/zip/ZipEntry.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 4402db26..74f7ff3d 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 @@ -201,10 +201,10 @@ public class ZipEntry { */ public ZipEntry build() throws ZipException { Calendar calendar = Calendar.getInstance(); - int time = (calendar.get(Calendar.YEAR) - 60) << 25 | (calendar.get(Calendar.MONTH) + 1) << 21 + // java time stamp to dos timestamp, dos time start 1980 + int time = (calendar.get(Calendar.YEAR) - 1980) << 25 | (calendar.get(Calendar.MONTH) + 1) << 21 | calendar.get(Calendar.DAY_OF_MONTH) << 16 | calendar.get(Calendar.HOUR_OF_DAY) << 11 - | calendar.get(Calendar.MINUTE) << 5 | calendar.get(Calendar.SECOND) >> 1 - + ((calendar.getTimeInMillis() % 2000) << 32); + | calendar.get(Calendar.MINUTE) << 5 | calendar.get(Calendar.SECOND) >> 1; CentralDirectory cd = addCenterDirectory(time); ZipEntryHeader zipEntryHeader = addZipEntryHeader(time); if (data == null) { -- Gitee From e7f2c9b5fab1e3169a9cc902a5a5309471b111b9 Mon Sep 17 00:00:00 2001 From: zfeixiang Date: Sat, 27 Jul 2024 21:17:42 +0800 Subject: [PATCH 28/28] code check Signed-off-by: zfeixiang --- .../hapsigntool/codesigning/datastructure/HapInfoSegment.java | 3 --- .../ohos/hapsigntool/codesigning/datastructure/SignInfo.java | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) 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 ff5ef999..42865040 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 @@ -127,9 +127,6 @@ 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) { - LOGGER.info("Maybe the tool is out-of-date, extensionNum {}", inHapSignInfo.getExtensionNum()); - } if (inHapSignInfo.getExtensionByType(MerkleTreeExtension.MERKLE_TREE_INLINED) == null) { throw new VerifyCodeSignException("No merkle tree extension is found in HapInfoSegment"); } 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 03c2e6f1..748b92a2 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 @@ -247,7 +247,8 @@ public class SignInfo { bf.get(inSalt); int inExtensionNum = bf.getInt(); if (inExtensionNum < 0 || inExtensionNum > MAX_EXTENSION_NUM) { - LOGGER.info("Invalid extensionNum {} of SignInfo", inExtensionNum); + LOGGER.info("The signature information may be generated by an new tool, extensionNum {} of SignInfo", + inExtensionNum); } int inExtensionOffset = bf.getInt(); if (inExtensionOffset < 0 || inExtensionOffset % 4 != 0) { -- Gitee