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 
18 #include <stdbool.h>
19 #include <stddef.h>
20 
21 #include "hks_client_ipc_serialization.h"
22 #include "hks_log.h"
23 #include "hks_mem.h"
24 #include "hks_request.h"
25 #include "hks_template.h"
26 
IsSliceCmd(uint32_t cmdId)27 static bool IsSliceCmd(uint32_t cmdId)
28 {
29     return (cmdId == HKS_MSG_SIGN) || (cmdId == HKS_MSG_VERIFY) || (cmdId == HKS_MSG_ENCRYPT) ||
30         (cmdId == HKS_MSG_DECRYPT) || (cmdId == HKS_MSG_MAC);
31 }
32 
GetBlobBufSize(const struct HksBlob * blob,uint32_t * bufSize)33 static uint32_t GetBlobBufSize(const struct HksBlob *blob, uint32_t *bufSize)
34 {
35     if (IsAdditionOverflow(blob->size, DEFAULT_ALIGN_MASK_SIZE)) {
36         return HKS_ERROR_INVALID_ARGUMENT;
37     }
38     if (IsAdditionOverflow(ALIGN_SIZE(blob->size), sizeof(blob->size))) {
39         return HKS_ERROR_INVALID_ARGUMENT;
40     }
41     *bufSize = ALIGN_SIZE(blob->size) + sizeof(blob->size);
42     return HKS_SUCCESS;
43 }
44 
GetParamSize(const struct HksBlob * key,const struct HksParamSet * paramSet,uint32_t * bufSize)45 static uint32_t GetParamSize(const struct HksBlob *key, const struct HksParamSet *paramSet, uint32_t *bufSize)
46 {
47     if ((key->size > MAX_PROCESS_SIZE) || (paramSet->paramSetSize > MAX_PROCESS_SIZE)) {
48         return HKS_ERROR_INVALID_ARGUMENT;
49     }
50 
51     *bufSize = ALIGN_SIZE(key->size) + sizeof(key->size) + ALIGN_SIZE(paramSet->paramSetSize);
52     return HKS_SUCCESS;
53 }
54 
GetDataSize(uint32_t cmdId,const struct HksBlob * inData,const struct HksBlob * outData,uint32_t * bufSize)55 static uint32_t GetDataSize(uint32_t cmdId, const struct HksBlob *inData, const struct HksBlob *outData,
56     uint32_t *bufSize)
57 {
58     uint32_t inBuffData;
59     HKS_IF_NOT_SUCC_RETURN(GetBlobBufSize(inData, &inBuffData), HKS_ERROR_INVALID_ARGUMENT)
60 
61     uint32_t bufOutDataSize;
62     if (cmdId == HKS_MSG_VERIFY) {
63         HKS_IF_NOT_SUCC_RETURN(GetBlobBufSize(outData, &bufOutDataSize), HKS_ERROR_INVALID_ARGUMENT)
64     } else {
65         bufOutDataSize = sizeof(outData->size);
66     }
67 
68     if (IsAdditionOverflow(inBuffData, bufOutDataSize)) {
69         return HKS_ERROR_INVALID_ARGUMENT;
70     }
71     *bufSize = inBuffData + bufOutDataSize;
72     return HKS_SUCCESS;
73 }
74 
ProcessDataOnce(uint32_t cmdId,const struct HksBlob * key,const struct HksParamSet * paramSet,struct HksBlob * inData,struct HksBlob * outData)75 static int32_t ProcessDataOnce(uint32_t cmdId, const struct HksBlob *key, const struct HksParamSet *paramSet,
76     struct HksBlob *inData, struct HksBlob *outData)
77 {
78     HKS_LOG_D("invoke ProcessOnce cmdId %" LOG_PUBLIC "u", cmdId);
79 
80     uint32_t paramBufSize, dataBufSize;
81     if ((GetParamSize(key, paramSet, &paramBufSize) != HKS_SUCCESS) ||
82         (GetDataSize(cmdId, inData, outData, &dataBufSize) != HKS_SUCCESS)) {
83         return HKS_ERROR_INVALID_ARGUMENT;
84     }
85     uint32_t totalBufSize = paramBufSize + dataBufSize;
86     uint8_t *buffer = (uint8_t *)HksMalloc(totalBufSize);
87     HKS_IF_NULL_RETURN(buffer, HKS_ERROR_MALLOC_FAIL)
88     struct HksBlob ipcBlob = { totalBufSize, buffer };
89 
90     uint32_t offset = 0;
91     int32_t ret = HksOnceParamPack(&ipcBlob, key, paramSet, &offset);
92     if (ret != HKS_SUCCESS) {
93         HKS_LOG_E("HksOnceParamPack fail");
94         HKS_FREE_BLOB(ipcBlob);
95         return ret;
96     }
97 
98     if (cmdId == HKS_MSG_VERIFY) {
99         ret = HksOnceDataPack(&ipcBlob, inData, outData, NULL, &offset);
100     } else {
101         ret = HksOnceDataPack(&ipcBlob, inData, NULL, outData, &offset);
102     }
103     if (ret != HKS_SUCCESS) {
104         HKS_LOG_E("HksOnceDataPack fail");
105         HKS_FREE_BLOB(ipcBlob);
106         return ret;
107     }
108 
109     if (cmdId == HKS_MSG_VERIFY) {
110         ret = HksSendRequest(cmdId, &ipcBlob, NULL, paramSet);
111     } else {
112         ret = HksSendRequest(cmdId, &ipcBlob, outData, paramSet);
113     }
114     HKS_FREE_BLOB(ipcBlob);
115     return ret;
116 }
117 
HksSliceDataEntry(uint32_t cmdId,const struct HksBlob * key,const struct HksParamSet * paramSet,struct HksBlob * inData,struct HksBlob * outData)118 int32_t HksSliceDataEntry(uint32_t cmdId, const struct HksBlob *key, const struct HksParamSet *paramSet,
119     struct HksBlob *inData, struct HksBlob *outData)
120 {
121     if (!IsSliceCmd(cmdId)) {
122         HKS_LOG_E("cmd %" LOG_PUBLIC "u not support slice!", cmdId);
123         return HKS_ERROR_INVALID_ARGUMENT;
124     }
125 
126     uint32_t paramBufSize;
127     uint32_t dataBufSize;
128     if ((GetParamSize(key, paramSet, &paramBufSize) != HKS_SUCCESS) ||
129         (GetDataSize(cmdId, inData, outData, &dataBufSize) != HKS_SUCCESS)) {
130         return HKS_ERROR_INVALID_ARGUMENT;
131     }
132     if (IsAdditionOverflow(paramBufSize, dataBufSize)) {
133         return HKS_ERROR_INVALID_ARGUMENT;
134     }
135 
136     uint32_t totalBufSize = paramBufSize + dataBufSize;
137     if (totalBufSize <= MAX_PROCESS_SIZE) {
138         return ProcessDataOnce(cmdId, key, paramSet, inData, outData);
139     }
140     return HKS_ERROR_INVALID_ARGUMENT;
141 }
142