• 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(unsigned int signAlgorithm)25 int GetDigestAlgorithmId(unsigned int 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,int blockLen,int alg,const HapBuf * result,int * offset)43 static int ComputeBlockHash(const char *block, int blockLen, int alg, const HapBuf *result, int *offset)
44 {
45     int 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     int 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(int fileSize,int coreDirectorySize,int eocdSize,int rootHashLen)94 static int GetChunkSumCount(int fileSize, int coreDirectorySize, int eocdSize, int rootHashLen)
95 {
96     int chunkSize = HASH_BLOB_LEN;
97     int maxSize = INT_MAX - chunkSize;
98     if (fileSize > maxSize || coreDirectorySize > maxSize || eocdSize > maxSize) {
99         return 0;
100     }
101     int 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 int digestAlgorithm,int fp,const SignatureInfo * signInfo,const HapBuf * chunkDigest,const HapBuf * fianlDigest)111 static int ComputeDigestsWithOptionalBlock(const int digestAlgorithm, int fp, const SignatureInfo *signInfo,
112     const HapBuf *chunkDigest, const HapBuf *fianlDigest)
113 {
114     int ret, readLen;
115     int rst = V_ERR;
116     char *rawBuf = NULL;
117     unsigned char* outbuf = NULL;
118     int 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     int 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(int digestAlgorithm,mbedtls_md_context_t * mdCtx,const mbedtls_md_info_t * mdInfo,int readLen,size_t * hlen)161 static int HapUpdateDigistHead(int digestAlgorithm, mbedtls_md_context_t *mdCtx, const mbedtls_md_info_t *mdInfo,
162     int readLen, size_t *hlen)
163 {
164     mbedtls_md_init(mdCtx);
165     int ret = mbedtls_md_setup(mdCtx, mdInfo, 0);
166     if (ret != 0) {
167         return V_ERR;
168     }
169     *hlen = mbedtls_md_get_size(mdInfo);
170     if (*hlen == 0 || *hlen > MAX_HASH_SIZE) {
171         return V_ERR;
172     }
173     ret = mbedtls_md_starts(mdCtx);
174     if (ret != 0) {
175         return V_ERR;
176     }
177     unsigned char chunkContentPrefix[HAP_DIGEST_PRIFIX_LEN] = {HAP_SECOND_LEVEL_CHUNK_PREFIX, 0, 0, 0, 0};
178     if (memcpy_s((chunkContentPrefix + 1), HAP_DIGEST_PRIFIX_LEN - 1, (&readLen), sizeof(int)) != EOK) {
179         return V_ERR;
180     }
181     ret = mbedtls_md_update(mdCtx, chunkContentPrefix, HAP_DIGEST_PRIFIX_LEN);
182     if (ret != 0) {
183         return V_ERR;
184     }
185     return V_OK;
186 }
187 
UpdateSmallBlock(int readLen,const int fp,mbedtls_md_context_t * mdCtx)188 static int UpdateSmallBlock(int readLen, const int fp, mbedtls_md_context_t *mdCtx)
189 {
190     int readLenLeft = readLen;
191     while (readLenLeft > 0) {
192         int onceRead = (readLenLeft > ONCE_READ_LEN) ? ONCE_READ_LEN : readLenLeft;
193         unsigned char *onceBuf = APPV_MALLOC(onceRead);
194         P_NULL_RETURN_WTTH_LOG(onceBuf);
195         int len = read(fp, onceBuf, sizeof(char) * onceRead);
196         if (len != onceRead) {
197             LOG_ERROR("fread err: %d, %d", len, onceRead);
198             APPV_FREE(onceBuf);
199             return V_ERR;
200         }
201         int ret = mbedtls_md_update(mdCtx, onceBuf, onceRead);
202         APPV_FREE(onceBuf);
203         P_ERR_RETURN_WTTH_LOG(ret);
204         readLenLeft -= onceRead;
205     }
206     return V_OK;
207 }
208 
ComputerFileHash(const SignatureInfo * signInfo,int digestAlgorithm,const int fp,const HapBuf * chunkDigest,int * offset)209 static int ComputerFileHash(const SignatureInfo *signInfo, int digestAlgorithm, const int fp,
210     const HapBuf *chunkDigest, int *offset)
211 {
212     mbedtls_md_context_t *mdCtx = APPV_MALLOC(sizeof(mbedtls_md_context_t));
213     P_NULL_RETURN_WTTH_LOG(mdCtx);
214     lseek(fp, 0, SEEK_SET);
215     int pos = 0;
216     int rawBufLen = signInfo->fullSignBlockOffset;
217     while (rawBufLen > 0) {
218         size_t hlen = 0;
219         int readLen = (rawBufLen > HASH_BLOB_LEN) ? HASH_BLOB_LEN : rawBufLen;
220         const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type((mbedtls_md_type_t)digestAlgorithm);
221         if (mdInfo == NULL) {
222             APPV_FREE(mdCtx);
223             return V_ERR;
224         }
225         int ret = HapUpdateDigistHead(digestAlgorithm, mdCtx, mdInfo, readLen, &hlen);
226         P_ERR_GOTO_WTTH_LOG(ret);
227         LOG_INFO("content: %d, %d", rawBufLen, pos);
228         ret = UpdateSmallBlock(readLen, fp, mdCtx);
229         P_ERR_GOTO_WTTH_LOG(ret);
230         rawBufLen -= readLen;
231         pos += readLen;
232         unsigned char *outbuf = APPV_MALLOC(hlen);
233         P_NULL_GOTO_WTTH_LOG(outbuf);
234         ret = mbedtls_md_finish(mdCtx, outbuf);
235         HapPutData(chunkDigest, *offset, outbuf, hlen);
236         (void)memset_s(outbuf, hlen, 0, hlen);
237         *offset += hlen;
238         APPV_FREE(outbuf);
239         P_ERR_GOTO_WTTH_LOG(ret);
240         mbedtls_md_free(mdCtx);
241     }
242     APPV_FREE(mdCtx);
243     return V_OK;
244 EXIT:
245     mbedtls_md_free(mdCtx);
246     APPV_FREE(mdCtx);
247     return V_ERR;
248 }
249 
ComputerCoreDirHash(const SignatureInfo * signInfo,int digestAlgorithm,const int fp,const HapBuf * chunkDigest,int * offset)250 static int ComputerCoreDirHash(const SignatureInfo *signInfo, int digestAlgorithm, const int fp,
251     const HapBuf *chunkDigest, int *offset)
252 {
253     int centralDirSize = signInfo->hapEocdOffset - signInfo->hapCoreDirOffset;
254     if (centralDirSize <= 0) {
255         return V_ERR;
256     }
257     char *dirBuf = APPV_MALLOC(centralDirSize);
258     P_NULL_RETURN_WTTH_LOG(dirBuf);
259     lseek(fp, signInfo->hapCoreDirOffset, SEEK_SET);
260     int len = read(fp, dirBuf, sizeof(char) * centralDirSize);
261     if (len != centralDirSize) {
262         LOG_ERROR("fread err: %d, %d", len, centralDirSize);
263         APPV_FREE(dirBuf);
264         return V_ERR;
265     }
266     int ret = ComputeBlockHash(dirBuf, centralDirSize, digestAlgorithm, chunkDigest, offset);
267     (void)memset_s(dirBuf, centralDirSize, 0, centralDirSize);
268     APPV_FREE(dirBuf);
269     P_ERR_RETURN_WTTH_LOG(ret);
270     return V_OK;
271 }
272 
ComputerEocdHash(const SignatureInfo * signInfo,int digestAlgorithm,const int fp,const HapBuf * chunkDigest,int * offset)273 static int ComputerEocdHash(const SignatureInfo *signInfo, int digestAlgorithm, const int fp,
274     const HapBuf *chunkDigest, int *offset)
275 {
276     if (signInfo->hapEocdSize <= 0) {
277         return V_ERR;
278     }
279     HapEocd *eocdBuf = APPV_MALLOC(signInfo->hapEocdSize);
280     P_NULL_RETURN_WTTH_LOG(eocdBuf);
281     lseek(fp, signInfo->hapEocdOffset, SEEK_SET);
282     int len = read(fp, eocdBuf, signInfo->hapEocdSize);
283     if (len != signInfo->hapEocdSize) {
284         LOG_ERROR("fread err: %d, %d", len, signInfo->hapEocdSize);
285         APPV_FREE(eocdBuf);
286         return V_ERR;
287     }
288     HapPutInt32((unsigned char*)(&(eocdBuf->eocdHead.coreDirOffset)), sizeof(int), signInfo->fullSignBlockOffset);
289     int ret = ComputeBlockHash((char *)(eocdBuf), len, digestAlgorithm, chunkDigest, offset);
290     (void)memset_s(eocdBuf, signInfo->hapEocdSize, 0, signInfo->hapEocdSize);
291     APPV_FREE(eocdBuf);
292     P_ERR_RETURN_WTTH_LOG(ret);
293     return V_OK;
294 }
295 
VerifyIntegrityChunk(int digestAlgorithm,const int fp,const SignatureInfo * signInfo,const HapBuf * actualDigest)296 bool VerifyIntegrityChunk(int digestAlgorithm, const int fp,
297     const SignatureInfo *signInfo, const HapBuf *actualDigest)
298 {
299     if (signInfo == NULL || actualDigest == NULL || actualDigest->buffer == NULL) {
300         return false;
301     }
302     int centralDirSize = signInfo->hapEocdOffset - signInfo->hapCoreDirOffset;
303     int rootHashLen = GetHashUnitLen(digestAlgorithm);
304     if (rootHashLen < 0) {
305         LOG_ERROR("alg error");
306         return false;
307     }
308     int sumCount = GetChunkSumCount(signInfo->fullSignBlockOffset, centralDirSize, signInfo->hapEocdSize, rootHashLen);
309     if (sumCount == 0) {
310         LOG_ERROR("sum count error");
311         return false;
312     }
313     int sumOfChunksLen = HAP_DIGEST_PRIFIX_LEN + sumCount * rootHashLen;
314     HapBuf chunkDigest = {0};
315     if (!CreateHapBuffer(&chunkDigest, sumOfChunksLen)) {
316         return false;
317     }
318     LOG_INFO("alg: %d", digestAlgorithm);
319     HapPutByte(&chunkDigest, 0, HAP_FIRST_LEVEL_CHUNK_PREFIX);
320     HapSetInt32(&chunkDigest, 1, sumCount);
321     int offset = HAP_DIGEST_PRIFIX_LEN;
322     int ret;
323     ret = ComputerFileHash(signInfo, digestAlgorithm, fp, &chunkDigest, &offset);
324     P_ERR_GOTO_WTTH_LOG(ret);
325     ret = ComputerCoreDirHash(signInfo, digestAlgorithm, fp, &chunkDigest, &offset);
326     P_ERR_GOTO_WTTH_LOG(ret);
327     ret = ComputerEocdHash(signInfo, digestAlgorithm, fp, &chunkDigest, &offset);
328     P_ERR_GOTO_WTTH_LOG(ret);
329     ret = ComputeDigestsWithOptionalBlock(digestAlgorithm, fp, signInfo, &chunkDigest, actualDigest);
330     P_ERR_GOTO_WTTH_LOG(ret);
331     ClearHapBuffer(&chunkDigest);
332     LOG_INFO("finish");
333     return true;
334 EXIT:
335     LOG_ERROR("exit");
336     ClearHapBuffer(&chunkDigest);
337     return false;
338 }
339