• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 package com.ohos.hapsigntool.codesigning.datastructure;
17 
18 import com.ohos.hapsigntool.codesigning.exception.VerifyCodeSignException;
19 
20 import java.nio.ByteBuffer;
21 import java.nio.ByteOrder;
22 import java.util.Locale;
23 
24 /**
25  * segment header has three field:
26  * <p>
27  * u32 type: indicates the type of segment: fs-verity/so/hap info segment
28  * <p>
29  * u32 segment offset: the segment position based on the start of code sign block
30  * <p>
31  * u32 segment size: byte size of the segment
32  *
33  * @since 2023/09/08
34  */
35 public class SegmentHeader {
36     /**
37      * Byte size of SegmentHeader
38      */
39     public static final int SEGMENT_HEADER_LENGTH = 12;
40 
41     /**
42      * Fs-verity segment type
43      */
44     public static final int CSB_FSVERITY_INFO_SEG = 0x1;
45 
46     /**
47      * Hap info segment type
48      */
49     public static final int CSB_HAP_META_SEG = 0x2;
50 
51     /**
52      * So info segment type
53      */
54     public static final int CSB_NATIVE_LIB_INFO_SEG = 0x3;
55 
56     private final int type;
57 
58     private int segmentOffset;
59 
60     private final int segmentSize;
61 
62     /**
63      * Constructor for SegmentHeader
64      *
65      * @param type        segment type
66      * @param segmentSize byte size of the segment
67      */
SegmentHeader(int type, int segmentSize)68     public SegmentHeader(int type, int segmentSize) {
69         this(type, 0, segmentSize);
70     }
71 
72     /**
73      * Constructor for SegmentHeader
74      *
75      * @param type          segment type
76      * @param segmentOffset segment offset based on the start of code sign block
77      * @param segmentSize   byte size of segment
78      */
SegmentHeader(int type, int segmentOffset, int segmentSize)79     public SegmentHeader(int type, int segmentOffset, int segmentSize) {
80         this.type = type;
81         this.segmentOffset = segmentOffset;
82         this.segmentSize = segmentSize;
83     }
84 
getType()85     public int getType() {
86         return type;
87     }
88 
setSegmentOffset(int offset)89     public void setSegmentOffset(int offset) {
90         this.segmentOffset = offset;
91     }
92 
getSegmentOffset()93     public int getSegmentOffset() {
94         return segmentOffset;
95     }
96 
getSegmentSize()97     public int getSegmentSize() {
98         return segmentSize;
99     }
100 
101     /**
102      * Converts SegmentHeader to a newly created byte array
103      *
104      * @return Byte array representation of SegmentHeader
105      */
toByteArray()106     public byte[] toByteArray() {
107         ByteBuffer bf = ByteBuffer.allocate(SEGMENT_HEADER_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
108         bf.putInt(type);
109         bf.putInt(segmentOffset);
110         bf.putInt(segmentSize);
111         return bf.array();
112     }
113 
114     /**
115      * Init the SegmentHeader by a byte array
116      *
117      * @param bytes Byte array representation of a SegmentHeader object
118      * @return a newly created SegmentHeader object
119      * @throws VerifyCodeSignException parsing result invalid
120      */
fromByteArray(byte[] bytes)121     public static SegmentHeader fromByteArray(byte[] bytes) throws VerifyCodeSignException {
122         if (bytes.length != SEGMENT_HEADER_LENGTH) {
123             throw new VerifyCodeSignException("Invalid size of SegmentHeader");
124         }
125         ByteBuffer bf = ByteBuffer.allocate(SEGMENT_HEADER_LENGTH).order(ByteOrder.LITTLE_ENDIAN);
126         bf.put(bytes);
127         bf.rewind();
128         int inType = bf.getInt();
129         if ((inType != CSB_FSVERITY_INFO_SEG) && (inType != CSB_HAP_META_SEG) && (inType != CSB_NATIVE_LIB_INFO_SEG)) {
130             throw new VerifyCodeSignException("Invalid type of SegmentHeader");
131         }
132         int inSegmentOffset = bf.getInt();
133         // segment offset is always larger than the size of CodeSignBlockHeader
134         if (inSegmentOffset < CodeSignBlockHeader.size()) {
135             throw new VerifyCodeSignException("Invalid segmentOffset of SegmentHeader");
136         }
137         int inSegmentSize = bf.getInt();
138         if (inSegmentSize < 0) {
139             throw new VerifyCodeSignException("Invalid segmentSize of SegmentHeader");
140         }
141         if ((inType == CSB_FSVERITY_INFO_SEG) && (inSegmentSize != FsVerityInfoSegment.FS_VERITY_INFO_SEGMENT_SIZE)) {
142             throw new VerifyCodeSignException("Invalid segmentSize of fs-verity SegmentHeader");
143         }
144         return new SegmentHeader(inType, inSegmentOffset, inSegmentSize);
145     }
146 
147     /**
148      * Return a string representation of the object
149      *
150      * @return string representation of the object
151      */
toString()152     public String toString() {
153         return String.format(Locale.ROOT, "Segment Header: type=%d, seg_offset = %d, seg_size = %d", this.type,
154             this.segmentOffset, this.segmentSize);
155     }
156 }
157