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_samgr_client.h"
17 #include "hks_request.h"
18 #include "hks_template.h"
19 #include "huks_service_ipc_interface_code.h"
20
21 #include "iproxy_client.h"
22 #include "registry.h"
23
24 #include <unistd.h>
25
SynchronizeOutput(const struct HksIpcHandle * reply,struct HksBlob * outBlob)26 static int32_t SynchronizeOutput(const struct HksIpcHandle *reply, struct HksBlob *outBlob)
27 {
28 if (reply->state != HKS_IPC_MSG_OK) {
29 HKS_LOG_E("ipc reply failed, ret = %d", reply->state);
30 return HKS_ERROR_IPC_MSG_FAIL;
31 }
32
33 int32_t callBackResult = HKS_ERROR_IPC_MSG_FAIL;
34 do {
35 bool ipcRet = ReadInt32(reply->io, &callBackResult);
36 if (!ipcRet) {
37 callBackResult = HKS_ERROR_IPC_MSG_FAIL;
38 break;
39 }
40
41 bool isNoneResponse = true;
42 ipcRet = ReadBool(reply->io, &isNoneResponse);
43 if (!ipcRet) {
44 callBackResult = HKS_ERROR_IPC_MSG_FAIL;
45 break;
46 }
47 if (isNoneResponse) {
48 break;
49 }
50
51 if (outBlob != NULL) {
52 uint32_t buffSize = 0;
53 ipcRet = ReadUint32(reply->io, &buffSize);
54 if (!ipcRet) {
55 callBackResult = HKS_ERROR_IPC_MSG_FAIL;
56 break;
57 }
58 if (buffSize == 0) {
59 HKS_LOG_I("ipc reply with no out data");
60 break;
61 }
62
63 // the ipc will ensure the validity of data-reading within limited and valid data size
64 const uint8_t *tmpUint8Array = ReadBuffer(reply->io, buffSize);
65 if (tmpUint8Array == NULL) {
66 callBackResult = HKS_ERROR_IPC_MSG_FAIL;
67 break;
68 }
69
70 if (memcpy_s(outBlob->data, outBlob->size, tmpUint8Array, buffSize) != EOK) {
71 callBackResult = HKS_ERROR_BUFFER_TOO_SMALL;
72 break;
73 }
74 outBlob->size = buffSize;
75 }
76 } while (0);
77
78 return callBackResult;
79 }
80
CurrentCallback(IOwner owner,int code,IpcIo * reply)81 static int CurrentCallback(IOwner owner, int code, IpcIo *reply)
82 {
83 (void)code;
84 struct HksIpcHandle *curReply = (struct HksIpcHandle *)owner;
85 if (curReply == NULL || reply == NULL) {
86 return HKS_ERROR_NULL_POINTER;
87 }
88 if (memcpy_s(curReply->io->bufferCur, curReply->io->bufferLeft, reply->bufferCur, reply->bufferLeft) != EOK) {
89 HKS_LOG_E("data copy for curReply failed, cur size is %zu, reply size is %zu", curReply->io->bufferLeft,
90 reply->bufferLeft);
91 curReply->state = HKS_IPC_MSG_ERROR;
92 curReply->io->bufferLeft = 0;
93 return HKS_ERROR_IPC_MSG_FAIL;
94 }
95 curReply->state = HKS_IPC_MSG_OK;
96 curReply->io->bufferLeft = reply->bufferLeft;
97 return HKS_SUCCESS;
98 }
99
WriteToIpcRequest(IpcIo * request,uint32_t outBlobSize,const struct HksBlob * inBlob)100 static int32_t WriteToIpcRequest(IpcIo *request, uint32_t outBlobSize, const struct HksBlob *inBlob)
101 {
102 bool ipcRet = WriteUint32(request, outBlobSize);
103 if (!ipcRet) {
104 return HKS_ERROR_IPC_MSG_FAIL;
105 }
106 ipcRet = WriteUint32(request, inBlob->size);
107 if (!ipcRet) {
108 return HKS_ERROR_IPC_MSG_FAIL;
109 }
110 ipcRet = WriteBuffer(request, inBlob->data, inBlob->size);
111 if (!ipcRet) {
112 return HKS_ERROR_IPC_MSG_FAIL;
113 }
114 return HKS_SUCCESS;
115 }
116
HksIpcCall(IUnknown * iUnknown,enum HksIpcInterfaceCode type,const struct HksBlob * inBlob,struct HksBlob * outBlob)117 static int32_t HksIpcCall(IUnknown *iUnknown, enum HksIpcInterfaceCode type, const struct HksBlob *inBlob,
118 struct HksBlob *outBlob)
119 {
120 /* Check input and inBlob */
121 int32_t ret = CheckBlob(inBlob);
122 if ((ret != HKS_SUCCESS) || (iUnknown == NULL)) {
123 return HKS_ERROR_NULL_POINTER;
124 }
125
126 IClientProxy *proxy = (IClientProxy *)iUnknown;
127
128 uint32_t outBlobSize = 0;
129 if (outBlob != NULL) {
130 outBlobSize = outBlob->size;
131 }
132
133 char *dataReq = NULL;
134 char *dataReply = NULL;
135 do {
136 dataReq = (char *)HksMalloc(MAX_IO_SIZE);
137 if (dataReq == NULL) {
138 ret = HKS_ERROR_MALLOC_FAIL;
139 break;
140 }
141 IpcIo request;
142 IpcIoInit(&request, dataReq, MAX_IO_SIZE, MAX_OBJ_NUM);
143
144 ret = WriteToIpcRequest(&request, outBlobSize, inBlob);
145 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "write to ipc request failed!")
146
147 dataReply = (char *)HksMalloc(MAX_IO_SIZE);
148 if (dataReply == NULL) {
149 ret = HKS_ERROR_MALLOC_FAIL;
150 break;
151 }
152 IpcIo reply;
153 IpcIoInit(&reply, dataReply, MAX_IO_SIZE, MAX_OBJ_NUM);
154
155 struct HksIpcHandle replyHandle = { .io = &reply, .state = HKS_IPC_MSG_BASE };
156
157 ret = (int32_t)proxy->Invoke((IClientProxy *)proxy, type, &request, (IOwner)&replyHandle, CurrentCallback);
158 HKS_IF_NOT_SUCC_BREAK(ret, HKS_ERROR_IPC_MSG_FAIL)
159
160 ret = SynchronizeOutput(&replyHandle, outBlob);
161 } while (0);
162 HKS_FREE(dataReq);
163 HKS_FREE(dataReply);
164
165 return ret;
166 }
167
HksSendRequestSync(enum HksIpcInterfaceCode type,const struct HksBlob * inBlob,struct HksBlob * outBlob)168 static int32_t HksSendRequestSync(enum HksIpcInterfaceCode type, const struct HksBlob *inBlob, struct HksBlob *outBlob)
169 {
170 IClientProxy *clientProxy = NULL;
171 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(HKS_SAMGR_SERVICE, HKS_SAMGR_FEATRURE);
172 if (iUnknown == NULL) {
173 HKS_LOG_E("get HKS_SAMGR_FEATRURE api failed");
174 return HKS_ERROR_NULL_POINTER;
175 }
176
177 int32_t ret = iUnknown->QueryInterface(iUnknown, DEFAULT_VERSION, (void **)&clientProxy);
178 if ((clientProxy == NULL) || (ret != 0)) {
179 HKS_LOG_E("get clientProxy failed");
180 return HKS_ERROR_NULL_POINTER;
181 }
182
183 ret = HksIpcCall((IUnknown *)clientProxy, type, inBlob, outBlob);
184 (void)clientProxy->Release((IUnknown *)clientProxy);
185
186 return ret;
187 }
188
HksSendRequest(enum HksIpcInterfaceCode type,const struct HksBlob * inBlob,struct HksBlob * outBlob,const struct HksParamSet * paramSet)189 int32_t HksSendRequest(enum HksIpcInterfaceCode type, const struct HksBlob *inBlob, struct HksBlob *outBlob,
190 const struct HksParamSet *paramSet)
191 {
192 (void)paramSet;
193 return HksSendRequestSync(type, inBlob, outBlob);
194 }
195