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_centraldirectory.h"
17 #include <fcntl.h>
18 #include <stdbool.h>
19 #include <string.h>
20 #include <sys/mman.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include "app_common.h"
25 #include "mbedtls/base64.h"
26 #include "mbedtls/md.h"
27 #include "mbedtls/pk.h"
28 #include "mbedtls/x509_crt.h"
29 #include "mbedtls_pkcs7.h"
30 #include "securec.h"
31 
HapPutByte(const HapBuf * hapBuffer,int32_t offset,char value)32 void HapPutByte(const HapBuf *hapBuffer, int32_t offset, char value)
33 {
34     if (hapBuffer == NULL || hapBuffer->buffer == NULL) {
35         return;
36     }
37     if ((offset >= 0) && (hapBuffer->len - offset >= (int)(sizeof(value)))) {
38         *(char *)((char *)hapBuffer->buffer + offset) = value;
39     }
40     return;
41 }
42 
HapPutData(const HapBuf * hapBuffer,int32_t offset,const unsigned char * data,int32_t len)43 void HapPutData(const HapBuf *hapBuffer, int32_t offset, const unsigned char *data, int32_t len)
44 {
45     if (hapBuffer == NULL || hapBuffer->buffer == NULL) {
46         return;
47     }
48     if ((data != NULL) && (offset >= 0) && len > 0 && ((hapBuffer->len - offset) >= len)) {
49         if (memcpy_s(((unsigned char *)hapBuffer->buffer + offset), (hapBuffer->len - offset), data, len) != EOK) {
50             LOG_ERROR("memcpy_s fail");
51         }
52     }
53 }
54 
HapSetInt32(const HapBuf * buffer,int32_t offset,int32_t value)55 void HapSetInt32(const HapBuf *buffer, int32_t offset, int32_t value)
56 {
57     if (value < 0) {
58         LOG_ERROR("int32 value of out range: %d", value);
59         return;
60     }
61     if (buffer == NULL || buffer->buffer == NULL) {
62         return;
63     }
64     if ((offset >= 0) && ((buffer->len - offset) >= (int)(sizeof(value)))) {
65         HapPutInt32((unsigned char *)buffer->buffer + offset, buffer->len - offset, (int)(value));
66     }
67     return;
68 }
69 
CreateHapBuffer(HapBuf * hapBuffer,int32_t len)70 bool CreateHapBuffer(HapBuf *hapBuffer, int32_t len)
71 {
72     if (hapBuffer == NULL || len <= 0) {
73         LOG_ERROR("create buf fail, buf is null");
74         return false;
75     }
76     hapBuffer->buffer = APPV_MALLOC(len);
77     if (hapBuffer->buffer == NULL) {
78         LOG_ERROR("create buf fail");
79         return false;
80     }
81     hapBuffer->len = len;
82     return true;
83 }
84 
ClearHapBuffer(HapBuf * hapBuffer)85 void ClearHapBuffer(HapBuf *hapBuffer)
86 {
87     if (hapBuffer == NULL || hapBuffer->buffer == NULL) {
88         return;
89     }
90     (void)memset_s(hapBuffer->buffer, hapBuffer->len, 0, hapBuffer->len);
91     APPV_FREE(hapBuffer->buffer);
92     hapBuffer->buffer = NULL;
93     hapBuffer->len = 0;
94 }
95 
GetEocd(const FileRead * hapFile,HapEocd * hapEocd,int32_t * eocdOffset)96 static bool GetEocd(const FileRead *hapFile, HapEocd *hapEocd, int32_t *eocdOffset)
97 {
98     MmapInfo mmapInfo = {0};
99     if (hapFile->len <= sizeof(MinEocd)) {
100         return false;
101     }
102     int32_t ret = HapMMap(hapFile->len, 0, &mmapInfo, hapFile);
103     if (ret != V_OK) {
104         LOG_ERROR("mmap not ok");
105         return false;
106     }
107     char *fileStart = (char *)(mmapInfo.mapAddr + mmapInfo.readMoreLen);
108     if (HapGetShort((unsigned char*)fileStart + hapFile->len - sizeof(short), sizeof(short)) == 0 &&
109         HapGetInt((unsigned char*)fileStart + hapFile->len - sizeof(MinEocd), sizeof(int)) == HAP_EOCD_MAGIC) {
110         if (memcpy_s(&hapEocd->eocdHead, sizeof(MinEocd),
111             fileStart + hapFile->len - sizeof(MinEocd), sizeof(MinEocd)) != EOK) {
112             HapMUnMap(mmapInfo.mapAddr, mmapInfo.mmapSize);
113             LOG_ERROR("copy error");
114             return false;
115         }
116         HapMUnMap(mmapInfo.mapAddr, mmapInfo.mmapSize);
117         *eocdOffset = hapFile->len - sizeof(MinEocd);
118         return true;
119     }
120     // only a few haps have comment and use this branch
121     int32_t maxReadLen = ((unsigned int)(hapFile->len - sizeof(MinEocd)) > UINT16_MAX_VALUE) ?
122         UINT16_MAX_VALUE : (hapFile->len - sizeof(MinEocd));
123     fileStart += hapFile->len - sizeof(MinEocd) - maxReadLen;
124     LOG_INFO("maxReadLen %d", maxReadLen);
125     for (int32_t i = 0; i < maxReadLen; i++) {
126         if ((HapGetShort((unsigned char*)fileStart + i + sizeof(MinEocd) - sizeof(short),
127             sizeof(short)) == (maxReadLen - i)) &&
128             (HapGetInt((unsigned char*)fileStart + i, sizeof(int)) == HAP_EOCD_MAGIC)) {
129             if (memcpy_s(&hapEocd->eocdHead, sizeof(MinEocd),
130                 fileStart + i, sizeof(MinEocd)) != EOK) {
131                 HapMUnMap(mmapInfo.mapAddr, mmapInfo.mmapSize);
132                 LOG_ERROR("copy error");
133                 return false;
134             }
135             HapMUnMap(mmapInfo.mapAddr, mmapInfo.mmapSize);
136             LOG_INFO("comment num %d", maxReadLen - i);
137             *eocdOffset = hapFile->len - sizeof(MinEocd) - (maxReadLen - i);
138             return true;
139         }
140     }
141     LOG_ERROR("can not find eocd");
142     HapMUnMap(mmapInfo.mapAddr, mmapInfo.mmapSize);
143     return false;
144 }
145 
FindSignature(const FileRead * hapFile,SignatureInfo * signInfo)146 bool FindSignature(const FileRead *hapFile, SignatureInfo *signInfo)
147 {
148     if (hapFile == NULL || signInfo == NULL) {
149         return false;
150     }
151     int32_t eocdOffset = 0;
152     HapEocd hapEocd = {0};
153     if (!GetEocd(hapFile, &hapEocd, &eocdOffset)) {
154         LOG_ERROR("find Eocd fail");
155         return false;
156     }
157     signInfo->hapEocdOffset = eocdOffset;
158     signInfo->hapEocdSize = hapFile->len - eocdOffset;
159     signInfo->hapCoreDirOffset = HapGetInt((unsigned char*)(&(hapEocd.eocdHead.coreDirOffset)), sizeof(int));
160     if (signInfo->hapCoreDirOffset <= 0 || signInfo->hapCoreDirOffset >= eocdOffset ||
161         signInfo->hapEocdSize <= 0 || signInfo->hapEocdOffset <= 0) {
162         LOG_ERROR("core dir error");
163         return false;
164     }
165     return true;
166 }
167 
ReadFileFullyFromOffset(const HapBuf * buffer,int32_t offset,const FileRead * file)168 int32_t ReadFileFullyFromOffset(const HapBuf *buffer, int32_t offset, const FileRead *file)
169 {
170     if (buffer == NULL || buffer->buffer == NULL || file == NULL) {
171         return DEST_BUFFER_IS_NULL;
172     }
173     if (offset < 0 || offset > file->len) {
174         return READ_OFFSET_OUT_OF_RANGE;
175     }
176     lseek(file->fp, offset, SEEK_SET);
177     int32_t readLen = read(file->fp, buffer->buffer, buffer->len);
178     if (readLen != buffer->len) {
179         LOG_ERROR("file read error %d --- %d", readLen, buffer->len);
180         return READ_OFFSET_OUT_OF_RANGE;
181     }
182     return buffer->len;
183 }
184