• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "hks_ipc_slice.h"
17 #include "hks_ipc_serialization.h"
18 #include "hks_log.h"
19 #include "hks_mem.h"
20 #include "hks_param.h"
21 #include "hks_request.h"
22 
23 #define CMD_INIT_OFFSET      1 /* offset from base cmd to init cmd. */
24 #define CMD_UPDATE_OFFSET    2 /* offset from base cmd to update cmd. */
25 #define CMD_FINAL_OFFSET     3 /* offset from base cmd to final cmd. */
26 
27 struct SliceParam {
28     uint64_t operationHandle;
29     struct HksBlob *inData;
30     struct HksBlob *outData;
31     const struct HksParamSet *paramSet;
32 };
33 
IsSliceCmd(uint32_t cmdId)34 static bool IsSliceCmd(uint32_t cmdId)
35 {
36     return (cmdId == HKS_MSG_SIGN) || (cmdId == HKS_MSG_VERIFY) || (cmdId == HKS_MSG_ENCRYPT) ||
37         (cmdId == HKS_MSG_DECRYPT) || (cmdId == HKS_MSG_MAC);
38 }
39 
GetBlobBufSize(const struct HksBlob * blob,uint32_t * bufSize)40 static uint32_t GetBlobBufSize(const struct HksBlob *blob, uint32_t *bufSize)
41 {
42     if (IsAdditionOverflow(blob->size, DEFAULT_ALIGN_MASK_SIZE)) {
43         return HKS_ERROR_INVALID_ARGUMENT;
44     }
45     if (IsAdditionOverflow(ALIGN_SIZE(blob->size), sizeof(blob->size))) {
46         return HKS_ERROR_INVALID_ARGUMENT;
47     }
48     *bufSize = ALIGN_SIZE(blob->size) + sizeof(blob->size);
49     return HKS_SUCCESS;
50 }
51 
GetParamSize(const struct HksBlob * key,const struct HksParamSet * paramSet,uint32_t * bufSize)52 static uint32_t GetParamSize(const struct HksBlob *key, const struct HksParamSet *paramSet, uint32_t *bufSize)
53 {
54     if ((key->size > MAX_PROCESS_SIZE) || (paramSet->paramSetSize > MAX_PROCESS_SIZE)) {
55         return HKS_ERROR_INVALID_ARGUMENT;
56     }
57 
58     *bufSize = ALIGN_SIZE(key->size) + sizeof(key->size) + ALIGN_SIZE(paramSet->paramSetSize);
59     return HKS_SUCCESS;
60 }
61 
GetDataSize(uint32_t cmdId,const struct HksBlob * inData,const struct HksBlob * outData,uint32_t * bufSize)62 static uint32_t GetDataSize(uint32_t cmdId, const struct HksBlob *inData, const struct HksBlob *outData,
63     uint32_t *bufSize)
64 {
65     uint32_t inBuffData;
66     if (GetBlobBufSize(inData, &inBuffData) != HKS_SUCCESS) {
67         return HKS_ERROR_INVALID_ARGUMENT;
68     }
69 
70     uint32_t bufOutDataSize;
71     if (cmdId == HKS_MSG_VERIFY) {
72         if (GetBlobBufSize(outData, &bufOutDataSize) != HKS_SUCCESS) {
73             return HKS_ERROR_INVALID_ARGUMENT;
74         }
75     } else {
76         bufOutDataSize = sizeof(outData->size);
77     }
78 
79     if (IsAdditionOverflow(inBuffData, bufOutDataSize)) {
80         return HKS_ERROR_INVALID_ARGUMENT;
81     }
82     *bufSize = inBuffData + bufOutDataSize;
83     return HKS_SUCCESS;
84 }
85 
ProcessDataOnce(uint32_t cmdId,const struct HksBlob * key,const struct HksParamSet * paramSet,struct HksBlob * inData,struct HksBlob * outData)86 static int32_t ProcessDataOnce(uint32_t cmdId, const struct HksBlob *key, const struct HksParamSet *paramSet,
87     struct HksBlob *inData, struct HksBlob *outData)
88 {
89     HKS_LOG_I("invoke ProcessOnce cmdId %u", cmdId);
90 
91     uint32_t paramBufSize, dataBufSize;
92     if ((GetParamSize(key, paramSet, &paramBufSize) != HKS_SUCCESS) ||
93         (GetDataSize(cmdId, inData, outData, &dataBufSize) != HKS_SUCCESS)) {
94         return HKS_ERROR_INVALID_ARGUMENT;
95     }
96     uint32_t totalBufSize = paramBufSize + dataBufSize;
97     uint8_t *buffer = (uint8_t *)HksMalloc(totalBufSize);
98     if (buffer == NULL) {
99         return HKS_ERROR_MALLOC_FAIL;
100     }
101     struct HksBlob ipcBlob = { totalBufSize, buffer };
102 
103     uint32_t offset = 0;
104     int32_t ret = HksOnceParamPack(&ipcBlob, key, paramSet, &offset);
105     if (ret != HKS_SUCCESS) {
106         HKS_LOG_E("HksOnceParamPack fail");
107         HKS_FREE_BLOB(ipcBlob);
108         return ret;
109     }
110 
111     if (cmdId == HKS_MSG_VERIFY) {
112         ret = HksOnceDataPack(&ipcBlob, inData, outData, NULL, &offset);
113     } else {
114         ret = HksOnceDataPack(&ipcBlob, inData, NULL, outData, &offset);
115     }
116     if (ret != HKS_SUCCESS) {
117         HKS_LOG_E("HksOnceDataPack fail");
118         HKS_FREE_BLOB(ipcBlob);
119         return ret;
120     }
121 
122     if (cmdId == HKS_MSG_VERIFY) {
123         ret = HksSendRequest(cmdId, &ipcBlob, NULL, paramSet);
124     } else {
125         ret = HksSendRequest(cmdId, &ipcBlob, outData, paramSet);
126     }
127     HKS_FREE_BLOB(ipcBlob);
128     return ret;
129 }
130 
SliceDataInit(uint32_t cmdId,const struct HksBlob * key,struct SliceParam * sliceParam)131 static int32_t SliceDataInit(uint32_t cmdId, const struct HksBlob *key, struct SliceParam *sliceParam)
132 {
133     HKS_LOG_I("ProcessInit cmdId %u", cmdId);
134 
135     uint32_t bufSize;
136     if (GetParamSize(key, sliceParam->paramSet, &bufSize) != HKS_SUCCESS) {
137         return HKS_ERROR_INVALID_ARGUMENT;
138     }
139     uint8_t *buffer = (uint8_t *)HksMalloc(bufSize);
140     if (buffer == NULL) {
141         return HKS_ERROR_MALLOC_FAIL;
142     }
143 
144     struct HksBlob inBlob = { bufSize, buffer };
145     struct HksBlob outBlob = { sizeof(sliceParam->operationHandle), (uint8_t *)&sliceParam->operationHandle };
146     int32_t ret = HksInitPack(&inBlob, key, sliceParam->paramSet);
147     if (ret != HKS_SUCCESS) {
148         HKS_LOG_E("HksInitPack fail");
149         HKS_FREE_BLOB(inBlob);
150         return ret;
151     }
152 
153     ret = HksSendRequest(cmdId, &inBlob, &outBlob, sliceParam->paramSet);
154     HKS_FREE_BLOB(inBlob);
155     return ret;
156 }
157 
GetUpdateParamSize(uint64_t operationHandle,const struct HksBlob * inData,const struct HksBlob * outData,uint32_t * bufSize)158 static int32_t GetUpdateParamSize(uint64_t operationHandle, const struct HksBlob *inData,
159     const struct HksBlob *outData, uint32_t *bufSize)
160 {
161     /* update size is guaranteed to be align */
162     *bufSize = sizeof(operationHandle) + sizeof(inData->size) + inData->size;
163     if (outData->size > 0) {
164         *bufSize += outData->size;
165     }
166     return HKS_SUCCESS;
167 }
168 
SliceDataUpdate(uint32_t cmdId,struct SliceParam * sliceParam,uint32_t * outSize)169 static int32_t SliceDataUpdate(uint32_t cmdId, struct SliceParam *sliceParam, uint32_t *outSize)
170 {
171     uint32_t cnt = (sliceParam->inData->size - 1) / MAX_PROCESS_SIZE; /* inSize has been checked: greater than 0 */
172     struct HksBlob tmpInData = *(sliceParam->inData);
173     tmpInData.size = MAX_PROCESS_SIZE;
174     struct HksBlob tmpOutData = { 0, NULL };
175     if (sliceParam->outData != NULL) {
176         tmpOutData.data = sliceParam->outData->data;
177         tmpOutData.size = MAX_PROCESS_SIZE;
178     }
179 
180     struct HksBlob ipcBlob = { 0, NULL };
181     if (GetUpdateParamSize(sliceParam->operationHandle, &tmpInData, &tmpOutData, &ipcBlob.size) != HKS_SUCCESS) {
182         return HKS_ERROR_INVALID_ARGUMENT;
183     }
184     ipcBlob.data = (uint8_t *)HksMalloc(ipcBlob.size);
185     if (ipcBlob.data == NULL) {
186         return HKS_ERROR_MALLOC_FAIL;
187     }
188 
189     uint32_t updateSize = 0;
190     for (uint32_t i = 0; i < cnt; i++) {
191         HKS_LOG_I("ProcessUpdate cmdId %u", cmdId);
192 
193         int32_t ret = HksUpdatePack(&ipcBlob, sliceParam->operationHandle, &tmpInData, &tmpOutData);
194         if (ret != HKS_SUCCESS) {
195             HKS_LOG_E("HksUpdatePack fail");
196             HKS_FREE_BLOB(ipcBlob);
197             return ret;
198         }
199 
200         ret = HksSendRequest(cmdId, &ipcBlob, &tmpOutData, sliceParam->paramSet);
201         if (ret != HKS_SUCCESS) {
202             HKS_LOG_E("fail to process update");
203             HKS_FREE_BLOB(ipcBlob);
204             return HKS_ERROR_BAD_STATE;
205         }
206         tmpInData.data += MAX_PROCESS_SIZE;
207         tmpOutData.data += tmpOutData.size;
208         updateSize += MAX_PROCESS_SIZE;
209     }
210 
211     sliceParam->inData->data += updateSize;
212     sliceParam->inData->size -= updateSize;
213     if ((sliceParam->outData != NULL) && (outSize != NULL)) {
214         sliceParam->outData->data += updateSize;
215         sliceParam->outData->size -= updateSize;
216         *outSize = updateSize;
217     }
218     HKS_FREE_BLOB(ipcBlob);
219     return HKS_SUCCESS;
220 }
221 
GetFinalParamSize(uint32_t cmdId,uint64_t operationHandle,const struct HksBlob * inData,const struct HksBlob * outData,uint32_t * bufSize)222 static int32_t GetFinalParamSize(uint32_t cmdId, uint64_t operationHandle, const struct HksBlob *inData,
223     const struct HksBlob *outData, uint32_t *bufSize)
224 {
225     if ((inData->size > MAX_PROCESS_SIZE) || (outData->size > MAX_PROCESS_SIZE)) {
226         return HKS_ERROR_INVALID_ARGUMENT;
227     }
228 
229     if (cmdId == HKS_MSG_VERIFY_FINAL) {
230         *bufSize = sizeof(operationHandle) + sizeof(inData->size) + ALIGN_SIZE(inData->size) +
231             sizeof(outData->size) + ALIGN_SIZE(outData->size);
232     } else {
233         *bufSize = sizeof(operationHandle) + sizeof(inData->size) + ALIGN_SIZE(inData->size) +
234             sizeof(outData->size);
235     }
236     return HKS_SUCCESS;
237 }
238 
SliceDataFinal(uint32_t cmdId,struct SliceParam * sliceParam)239 static int32_t SliceDataFinal(uint32_t cmdId, struct SliceParam *sliceParam)
240 {
241     HKS_LOG_I("enter SliceDataFinal cmdId %u", cmdId);
242 
243     struct HksBlob tmpInData = *(sliceParam->inData);
244     uint32_t bufSize;
245     if (GetFinalParamSize(cmdId, sliceParam->operationHandle, &tmpInData, sliceParam->outData,
246         &bufSize) != HKS_SUCCESS) {
247         return HKS_ERROR_INVALID_ARGUMENT;
248     }
249     uint8_t *buffer = (uint8_t *)HksMalloc(bufSize);
250     if (buffer == NULL) {
251         return HKS_ERROR_MALLOC_FAIL;
252     }
253 
254     struct HksBlob ipcBlob = { bufSize, buffer };
255     int32_t ret;
256     if (cmdId == HKS_MSG_VERIFY_FINAL) {
257         ret = HksFinalPack(&ipcBlob, sliceParam->operationHandle, &tmpInData, sliceParam->outData, NULL);
258     } else {
259         ret = HksFinalPack(&ipcBlob, sliceParam->operationHandle, &tmpInData, NULL, sliceParam->outData);
260     }
261     if (ret != HKS_SUCCESS) {
262         HKS_LOG_E("HksFinalPack fail");
263         HKS_FREE_BLOB(ipcBlob);
264         return ret;
265     }
266 
267     if (cmdId == HKS_MSG_VERIFY_FINAL) {
268         ret = HksSendRequest(cmdId, &ipcBlob, NULL, sliceParam->paramSet);
269     } else {
270         ret = HksSendRequest(cmdId, &ipcBlob, sliceParam->outData, sliceParam->paramSet);
271     }
272     HKS_FREE_BLOB(ipcBlob);
273     return ret;
274 }
275 
SliceData(uint32_t cmdId,const struct HksBlob * key,const struct HksParamSet * paramSet,struct HksBlob * inData,struct HksBlob * outData)276 static int32_t SliceData(uint32_t cmdId, const struct HksBlob *key, const struct HksParamSet *paramSet,
277     struct HksBlob *inData, struct HksBlob *outData)
278 {
279     HKS_LOG_I("enter SliceData, cmdId %u", cmdId);
280 
281     struct SliceParam sliceParam = {
282         .operationHandle = 0,
283         .inData = inData,
284         .outData = outData,
285         .paramSet = paramSet
286     };
287     int32_t ret = SliceDataInit(cmdId + CMD_INIT_OFFSET, key, &sliceParam);
288     if (ret != HKS_SUCCESS) {
289         HKS_LOG_E("SliceDataInit fail %d", ret);
290         return ret;
291     }
292 
293     uint32_t outSize = 0;
294     if ((cmdId == HKS_MSG_ENCRYPT) || (cmdId == HKS_MSG_DECRYPT)) {
295         ret = SliceDataUpdate(cmdId + CMD_UPDATE_OFFSET, &sliceParam, &outSize);
296     } else {
297         sliceParam.outData = NULL;
298         ret = SliceDataUpdate(cmdId + CMD_UPDATE_OFFSET, &sliceParam, NULL);
299         sliceParam.outData = outData;
300     }
301     if (ret != HKS_SUCCESS) {
302         HKS_LOG_E("SliceDataUpdate fail %d", ret);
303         return ret;
304     }
305 
306     ret = SliceDataFinal(cmdId + CMD_FINAL_OFFSET, &sliceParam);
307     if (ret != HKS_SUCCESS) {
308         HKS_LOG_E("SliceDataFinal fail %d", ret);
309         return ret;
310     }
311 
312     if (IsAdditionOverflow(outData->size, outSize)) {
313         return HKS_ERROR_INVALID_ARGUMENT;
314     }
315     outData->size += outSize;
316     return ret;
317 }
318 
CheckRsaMode(uint32_t cmdId,const struct HksParamSet * paramSet)319 static int32_t CheckRsaMode(uint32_t cmdId, const struct HksParamSet *paramSet)
320 {
321     if ((cmdId == HKS_MSG_ENCRYPT) || (cmdId == HKS_MSG_DECRYPT)) {
322         struct HksParam *algParam = NULL;
323         if (HksGetParam(paramSet, HKS_TAG_ALGORITHM, &algParam) != HKS_SUCCESS) {
324             HKS_LOG_E("HksGetParam failed! No algorithm tag!");
325             return HKS_ERROR_CHECK_GET_ALG_FAIL;
326         }
327         if (algParam->uint32Param == HKS_ALG_RSA) {
328             HKS_LOG_E("Slice does not support RSA encrypt!");
329             return HKS_ERROR_INVALID_ARGUMENT;
330         }
331     }
332     return HKS_SUCCESS;
333 }
334 
HksSliceDataEntry(uint32_t cmdId,const struct HksBlob * key,const struct HksParamSet * paramSet,struct HksBlob * inData,struct HksBlob * outData)335 int32_t HksSliceDataEntry(uint32_t cmdId, const struct HksBlob *key, const struct HksParamSet *paramSet,
336     struct HksBlob *inData, struct HksBlob *outData)
337 {
338     if (!IsSliceCmd(cmdId)) {
339         HKS_LOG_E("cmd %u not support slice!", cmdId);
340         return HKS_ERROR_INVALID_ARGUMENT;
341     }
342 
343     uint32_t paramBufSize;
344     uint32_t dataBufSize;
345     if ((GetParamSize(key, paramSet, &paramBufSize) != HKS_SUCCESS) ||
346         (GetDataSize(cmdId, inData, outData, &dataBufSize) != HKS_SUCCESS)) {
347         return HKS_ERROR_INVALID_ARGUMENT;
348     }
349     if (IsAdditionOverflow(paramBufSize, dataBufSize)) {
350         return HKS_ERROR_INVALID_ARGUMENT;
351     }
352 
353     uint32_t totalBufSize = paramBufSize + dataBufSize;
354     if (totalBufSize <= MAX_PROCESS_SIZE) {
355         return ProcessDataOnce(cmdId, key, paramSet, inData, outData);
356     }
357 
358     int32_t ret = CheckRsaMode(cmdId, paramSet);
359     if (ret != HKS_SUCCESS) {
360         return ret;
361     }
362     return SliceData(cmdId, key, paramSet, inData, outData);
363 }
364