• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2022 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 #include "app_verify_hap.h"
17 #include <stdbool.h>
18 #include <sys/mman.h>
19 #include <unistd.h>
20 #include "app_centraldirectory.h"
21 #include "app_common.h"
22 #include "app_verify.h"
23 #include "securec.h"
24 
GetDigestAlgorithmId(uint32_t signAlgorithm)25 int32_t GetDigestAlgorithmId(uint32_t signAlgorithm)
26 {
27     switch (signAlgorithm & ALGORITHM_MASK) {
28         case ALGORITHM_SHA256:
29         case ALGORITHM_PKCS1_SHA256:
30             return HASH_ALG_SHA256;
31         case ALGORITHM_SHA384:
32         case ALGORITHM_PKCS1_SHA384:
33             return HASH_ALG_SHA384;
34         case ALGORITHM_SHA512:
35         case ALGORITHM_PKCS1_SHA512:
36             return HASH_ALG_SHA512;
37         default:
38             LOG_ERROR("signAlgorithm: %u error", signAlgorithm);
39             return V_ERR;
40     }
41 }
42 
ComputeBlockHash(const char * block,int32_t blockLen,int32_t alg,const HapBuf * result,int32_t * offset)43 static int32_t ComputeBlockHash(const char *block, int32_t blockLen, int32_t alg, const HapBuf *result, int32_t *offset)
44 {
45     int32_t ret, readLen, rawBufLen;
46     const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type((mbedtls_md_type_t)alg);
47     P_NULL_RETURN_WTTH_LOG(mdInfo);
48     int32_t pos = 0;
49     rawBufLen = blockLen;
50     mbedtls_md_context_t *mdCtx = APPV_MALLOC(sizeof(mbedtls_md_context_t));
51     P_NULL_RETURN_WTTH_LOG(mdCtx);
52     LOG_INFO("alg: %d wholelen: %d", alg, rawBufLen);
53     while (rawBufLen > 0) {
54         mbedtls_md_init(mdCtx);
55         readLen = (rawBufLen > HASH_BLOB_LEN) ? HASH_BLOB_LEN : rawBufLen;
56         ret = mbedtls_md_setup(mdCtx, mdInfo, 0);
57         P_ERR_GOTO_WTTH_LOG(ret);
58         size_t hlen = mbedtls_md_get_size(mdInfo);
59         if (hlen == 0 || hlen > MAX_HASH_SIZE) {
60             goto EXIT;
61         }
62         ret = mbedtls_md_starts(mdCtx);
63         P_ERR_GOTO_WTTH_LOG(ret);
64         unsigned char chunkContentPrefix[HAP_DIGEST_PRIFIX_LEN] = {HAP_SECOND_LEVEL_CHUNK_PREFIX, 0, 0, 0, 0};
65         if (memcpy_s((chunkContentPrefix + 1), HAP_DIGEST_PRIFIX_LEN - 1, (&readLen), sizeof(int)) != EOK) {
66             LOG_ERROR("memcpy_s fail");
67             goto EXIT;
68         }
69         ret = mbedtls_md_update(mdCtx, chunkContentPrefix, HAP_DIGEST_PRIFIX_LEN);
70         P_ERR_GOTO_WTTH_LOG(ret);
71         LOG_INFO("content: %d, %d", rawBufLen, pos);
72         ret = mbedtls_md_update(mdCtx, (unsigned char *)block + pos, readLen);
73         P_ERR_GOTO_WTTH_LOG(ret);
74         rawBufLen -= readLen;
75         pos += readLen;
76         unsigned char *outbuf = APPV_MALLOC(hlen);
77         P_NULL_GOTO_WTTH_LOG(outbuf);
78         ret = mbedtls_md_finish(mdCtx, outbuf);
79         HapPutData(result, *offset, outbuf, hlen);
80         *offset += hlen;
81         (void)memset_s(outbuf, hlen, 0, hlen);
82         APPV_FREE(outbuf);
83         P_ERR_GOTO_WTTH_LOG(ret);
84         mbedtls_md_free(mdCtx);
85     }
86     APPV_FREE(mdCtx);
87     return V_OK;
88 EXIT:
89     mbedtls_md_free(mdCtx);
90     APPV_FREE(mdCtx);
91     return V_ERR;
92 }
93 
GetChunkSumCount(int32_t fileSize,int32_t coreDirectorySize,int32_t eocdSize,int32_t rootHashLen)94 static int32_t GetChunkSumCount(int32_t fileSize, int32_t coreDirectorySize, int32_t eocdSize, int32_t rootHashLen)
95 {
96     int32_t chunkSize = HASH_BLOB_LEN;
97     int32_t maxSize = INT_MAX - chunkSize;
98     if (fileSize > maxSize || coreDirectorySize > maxSize || eocdSize > maxSize) {
99         return 0;
100     }
101     int32_t count = ((fileSize - 1 + chunkSize) / chunkSize) + ((coreDirectorySize - 1 + chunkSize) / chunkSize) +
102         ((eocdSize - 1 + chunkSize) / chunkSize);
103     if (rootHashLen < 0 || (((INT_MAX - HAP_DIGEST_PRIFIX_LEN) / count) < rootHashLen)) {
104         LOG_ERROR("overflow count: %d, chunkDigestLen: %d", count, rootHashLen);
105         return 0;
106     }
107     LOG_INFO("get sum count %d", count);
108     return count;
109 }
110 
ComputeDigestsWithOptionalBlock(const int32_t digestAlgorithm,int32_t fp,const SignatureInfo * signInfo,const HapBuf * chunkDigest,const HapBuf * fianlDigest)111 static int32_t ComputeDigestsWithOptionalBlock(const int32_t digestAlgorithm, int32_t fp, const SignatureInfo *signInfo,
112     const HapBuf *chunkDigest, const HapBuf *fianlDigest)
113 {
114     int32_t ret, readLen;
115     int32_t rst = V_ERR;
116     char *rawBuf = NULL;
117     unsigned char* outbuf = NULL;
118     int32_t rootHashLen = GetHashUnitLen(digestAlgorithm);
119     LOG_INFO("rootHashLen %d", rootHashLen);
120     if (rootHashLen <= 0 || rootHashLen > MAX_HASH_SIZE) {
121         return rst;
122     }
123     const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type((mbedtls_md_type_t)digestAlgorithm);
124     P_NULL_RETURN_WTTH_LOG(mdInfo);
125     mbedtls_md_context_t *mdCtx = APPV_MALLOC(sizeof(mbedtls_md_context_t));
126     P_NULL_RETURN_WTTH_LOG(mdCtx);
127     mbedtls_md_init(mdCtx);
128     ret = mbedtls_md_setup(mdCtx, mdInfo, 0);
129     int32_t rawLen = 0;
130     BlockHead blockHead = {0};
131 
132     P_ERR_GOTO_WTTH_LOG(ret);
133     ret = mbedtls_md_starts(mdCtx);
134     P_ERR_GOTO_WTTH_LOG(ret);
135     readLen = chunkDigest->len;
136     LOG_INFO("readLen %d", readLen);
137     ret = mbedtls_md_update(mdCtx, chunkDigest->buffer, readLen);
138     P_ERR_GOTO_WTTH_LOG(ret);
139 
140     rawBuf = GetSignBlockByType(signInfo, fp, PROFILE_BLOCK_WITHSIGN_TYPE, &rawLen, &blockHead);
141     P_NULL_GOTO_WTTH_LOG(rawBuf);
142     readLen = rawLen;
143     LOG_INFO("signBuf %0x %d", rawBuf[0], readLen);
144     ret = mbedtls_md_update(mdCtx, (unsigned char *)rawBuf, readLen);
145     P_ERR_GOTO_WTTH_LOG(ret);
146     outbuf = (unsigned char *)APPV_MALLOC(rootHashLen);
147     P_NULL_GOTO_WTTH_LOG(outbuf);
148     ret = mbedtls_md_finish(mdCtx, outbuf);
149     P_ERR_GOTO_WTTH_LOG(ret);
150     HapPutData(fianlDigest, 0, outbuf, rootHashLen);
151     (void)memset_s(outbuf, rootHashLen, 0, rootHashLen);
152     rst = V_OK;
153 EXIT:
154     mbedtls_md_free(mdCtx);
155     APPV_FREE(mdCtx);
156     APPV_FREE(rawBuf);
157     APPV_FREE(outbuf);
158     return rst;
159 }
160 
HapUpdateDigistHead(int32_t digestAlgorithm,mbedtls_md_context_t * mdCtx,const mbedtls_md_info_t * mdInfo,int32_t readLen,size_t * hlen)161 static int32_t HapUpdateDigistHead(
162     int32_t digestAlgorithm, mbedtls_md_context_t *mdCtx,
163     const mbedtls_md_info_t *mdInfo, int32_t readLen, size_t *hlen)
164 {
165     mbedtls_md_init(mdCtx);
166     int32_t ret = mbedtls_md_setup(mdCtx, mdInfo, 0);
167     if (ret != 0) {
168         return V_ERR;
169     }
170     *hlen = mbedtls_md_get_size(mdInfo);
171     if (*hlen == 0 || *hlen > MAX_HASH_SIZE) {
172         return V_ERR;
173     }
174     ret = mbedtls_md_starts(mdCtx);
175     if (ret != 0) {
176         return V_ERR;
177     }
178     unsigned char chunkContentPrefix[HAP_DIGEST_PRIFIX_LEN] = {HAP_SECOND_LEVEL_CHUNK_PREFIX, 0, 0, 0, 0};
179     if (memcpy_s((chunkContentPrefix + 1), HAP_DIGEST_PRIFIX_LEN - 1, (&readLen), sizeof(int)) != EOK) {
180         return V_ERR;
181     }
182     ret = mbedtls_md_update(mdCtx, chunkContentPrefix, HAP_DIGEST_PRIFIX_LEN);
183     if (ret != 0) {
184         return V_ERR;
185     }
186     return V_OK;
187 }
188 
UpdateSmallBlock(int32_t readLen,const int32_t fp,mbedtls_md_context_t * mdCtx)189 static int32_t UpdateSmallBlock(int32_t readLen, const int32_t fp, mbedtls_md_context_t *mdCtx)
190 {
191     int32_t readLenLeft = readLen;
192     while (readLenLeft > 0) {
193         int32_t onceRead = (readLenLeft > ONCE_READ_LEN) ? ONCE_READ_LEN : readLenLeft;
194         unsigned char *onceBuf = APPV_MALLOC(onceRead);
195         P_NULL_RETURN_WTTH_LOG(onceBuf);
196         int32_t len = read(fp, onceBuf, sizeof(char) * onceRead);
197         if (len != onceRead) {
198             LOG_ERROR("fread err: %d, %d", len, onceRead);
199             APPV_FREE(onceBuf);
200             return V_ERR;
201         }
202         int32_t ret = mbedtls_md_update(mdCtx, onceBuf, onceRead);
203         APPV_FREE(onceBuf);
204         P_ERR_RETURN_WTTH_LOG(ret);
205         readLenLeft -= onceRead;
206     }
207     return V_OK;
208 }
209 
ComputerFileHash(const SignatureInfo * signInfo,int32_t digestAlgorithm,const int32_t fp,const HapBuf * chunkDigest,int32_t * offset)210 static int32_t ComputerFileHash(const SignatureInfo *signInfo, int32_t digestAlgorithm, const int32_t fp,
211     const HapBuf *chunkDigest, int32_t *offset)
212 {
213     mbedtls_md_context_t *mdCtx = APPV_MALLOC(sizeof(mbedtls_md_context_t));
214     P_NULL_RETURN_WTTH_LOG(mdCtx);
215     lseek(fp, 0, SEEK_SET);
216     int32_t pos = 0;
217     int32_t rawBufLen = signInfo->fullSignBlockOffset;
218     while (rawBufLen > 0) {
219         size_t hlen = 0;
220         int32_t readLen = (rawBufLen > HASH_BLOB_LEN) ? HASH_BLOB_LEN : rawBufLen;
221         const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type((mbedtls_md_type_t)digestAlgorithm);
222         if (mdInfo == NULL) {
223             APPV_FREE(mdCtx);
224             return V_ERR;
225         }
226         int32_t ret = HapUpdateDigistHead(digestAlgorithm, mdCtx, mdInfo, readLen, &hlen);
227         P_ERR_GOTO_WTTH_LOG(ret);
228         LOG_INFO("content: %d, %d", rawBufLen, pos);
229         ret = UpdateSmallBlock(readLen, fp, mdCtx);
230         P_ERR_GOTO_WTTH_LOG(ret);
231         rawBufLen -= readLen;
232         pos += readLen;
233         unsigned char *outbuf = APPV_MALLOC(hlen);
234         P_NULL_GOTO_WTTH_LOG(outbuf);
235         ret = mbedtls_md_finish(mdCtx, outbuf);
236         HapPutData(chunkDigest, *offset, outbuf, hlen);
237         (void)memset_s(outbuf, hlen, 0, hlen);
238         *offset += hlen;
239         APPV_FREE(outbuf);
240         P_ERR_GOTO_WTTH_LOG(ret);
241         mbedtls_md_free(mdCtx);
242     }
243     APPV_FREE(mdCtx);
244     return V_OK;
245 EXIT:
246     mbedtls_md_free(mdCtx);
247     APPV_FREE(mdCtx);
248     return V_ERR;
249 }
250 
ComputerCoreDirHash(const SignatureInfo * signInfo,int32_t digestAlgorithm,const int32_t fp,const HapBuf * chunkDigest,int32_t * offset)251 static int32_t ComputerCoreDirHash(const SignatureInfo *signInfo, int32_t digestAlgorithm, const int32_t fp,
252     const HapBuf *chunkDigest, int32_t *offset)
253 {
254     int32_t centralDirSize = signInfo->hapEocdOffset - signInfo->hapCoreDirOffset;
255     if (centralDirSize <= 0) {
256         return V_ERR;
257     }
258     char *dirBuf = APPV_MALLOC(centralDirSize);
259     P_NULL_RETURN_WTTH_LOG(dirBuf);
260     lseek(fp, signInfo->hapCoreDirOffset, SEEK_SET);
261     int32_t len = read(fp, dirBuf, sizeof(char) * centralDirSize);
262     if (len != centralDirSize) {
263         LOG_ERROR("fread err: %d, %d", len, centralDirSize);
264         APPV_FREE(dirBuf);
265         return V_ERR;
266     }
267     int32_t ret = ComputeBlockHash(dirBuf, centralDirSize, digestAlgorithm, chunkDigest, offset);
268     (void)memset_s(dirBuf, centralDirSize, 0, centralDirSize);
269     APPV_FREE(dirBuf);
270     P_ERR_RETURN_WTTH_LOG(ret);
271     return V_OK;
272 }
273 
ComputerEocdHash(const SignatureInfo * signInfo,int32_t digestAlgorithm,const int32_t fp,const HapBuf * chunkDigest,int32_t * offset)274 static int32_t ComputerEocdHash(const SignatureInfo *signInfo, int32_t digestAlgorithm, const int32_t fp,
275     const HapBuf *chunkDigest, int32_t *offset)
276 {
277     if (signInfo->hapEocdSize <= 0) {
278         return V_ERR;
279     }
280     HapEocd *eocdBuf = APPV_MALLOC(signInfo->hapEocdSize);
281     P_NULL_RETURN_WTTH_LOG(eocdBuf);
282     lseek(fp, signInfo->hapEocdOffset, SEEK_SET);
283     int32_t len = read(fp, eocdBuf, signInfo->hapEocdSize);
284     if (len != signInfo->hapEocdSize) {
285         LOG_ERROR("fread err: %d, %d", len, signInfo->hapEocdSize);
286         APPV_FREE(eocdBuf);
287         return V_ERR;
288     }
289     HapPutInt32((unsigned char*)(&(eocdBuf->eocdHead.coreDirOffset)), sizeof(int), signInfo->fullSignBlockOffset);
290     int32_t ret = ComputeBlockHash((char *)(eocdBuf), len, digestAlgorithm, chunkDigest, offset);
291     (void)memset_s(eocdBuf, signInfo->hapEocdSize, 0, signInfo->hapEocdSize);
292     APPV_FREE(eocdBuf);
293     P_ERR_RETURN_WTTH_LOG(ret);
294     return V_OK;
295 }
296 
VerifyIntegrityChunk(int32_t digestAlgorithm,const int32_t fp,const SignatureInfo * signInfo,const HapBuf * actualDigest)297 bool VerifyIntegrityChunk(int32_t digestAlgorithm, const int32_t fp,
298     const SignatureInfo *signInfo, const HapBuf *actualDigest)
299 {
300     if (signInfo == NULL || actualDigest == NULL || actualDigest->buffer == NULL) {
301         return false;
302     }
303     int32_t centralDirSize = signInfo->hapEocdOffset - signInfo->hapCoreDirOffset;
304     int32_t rootHashLen = GetHashUnitLen(digestAlgorithm);
305     if (rootHashLen < 0) {
306         LOG_ERROR("alg error");
307         return false;
308     }
309     int32_t sumCount = GetChunkSumCount(
310         signInfo->fullSignBlockOffset, centralDirSize, signInfo->hapEocdSize, rootHashLen);
311     if (sumCount == 0) {
312         LOG_ERROR("sum count error");
313         return false;
314     }
315     int32_t sumOfChunksLen = HAP_DIGEST_PRIFIX_LEN + sumCount * rootHashLen;
316     HapBuf chunkDigest = {0};
317     if (!CreateHapBuffer(&chunkDigest, sumOfChunksLen)) {
318         return false;
319     }
320     LOG_INFO("alg: %d", digestAlgorithm);
321     HapPutByte(&chunkDigest, 0, HAP_FIRST_LEVEL_CHUNK_PREFIX);
322     HapSetInt32(&chunkDigest, 1, sumCount);
323     int32_t offset = HAP_DIGEST_PRIFIX_LEN;
324     int32_t ret;
325     ret = ComputerFileHash(signInfo, digestAlgorithm, fp, &chunkDigest, &offset);
326     P_ERR_GOTO_WTTH_LOG(ret);
327     ret = ComputerCoreDirHash(signInfo, digestAlgorithm, fp, &chunkDigest, &offset);
328     P_ERR_GOTO_WTTH_LOG(ret);
329     ret = ComputerEocdHash(signInfo, digestAlgorithm, fp, &chunkDigest, &offset);
330     P_ERR_GOTO_WTTH_LOG(ret);
331     ret = ComputeDigestsWithOptionalBlock(digestAlgorithm, fp, signInfo, &chunkDigest, actualDigest);
332     P_ERR_GOTO_WTTH_LOG(ret);
333     ClearHapBuffer(&chunkDigest);
334     LOG_INFO("finish");
335     return true;
336 EXIT:
337     LOG_ERROR("exit");
338     ClearHapBuffer(&chunkDigest);
339     return false;
340 }
341