1 /*
2 * Copyright (c) 2022-2023 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 "cm_ipc_client.h"
17 #include "cm_ipc_client_serialization.h"
18 #include "cm_log.h"
19 #include "cm_mem.h"
20 #include "cm_param.h"
21 #include "cm_request.h"
22
GetAppCertInitBlob(struct CmBlob * outBlob)23 static int32_t GetAppCertInitBlob(struct CmBlob *outBlob)
24 {
25 uint32_t buffSize = sizeof(uint32_t) + sizeof(uint32_t) + MAX_LEN_SUBJECT_NAME +
26 sizeof(uint32_t) + MAX_LEN_CERT_ALIAS + sizeof(uint32_t) + MAX_LEN_URI +
27 sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint32_t) + MAX_LEN_CERTIFICATE_CHAIN;
28
29 outBlob->data = (uint8_t *)CmMalloc(buffSize);
30 if (outBlob->data == NULL) {
31 return CMR_ERROR_MALLOC_FAIL;
32 }
33 outBlob->size = buffSize;
34
35 return CM_SUCCESS;
36 }
37
CmGetAppCertFromBuffer(struct Credential * certificateInfo,const struct CmBlob * outData,uint32_t * offset)38 static int32_t CmGetAppCertFromBuffer(struct Credential *certificateInfo,
39 const struct CmBlob *outData, uint32_t *offset)
40 {
41 struct CmBlob blob;
42 int32_t ret = CmGetBlobFromBuffer(&blob, outData, offset);
43 if (ret != CM_SUCCESS) {
44 CM_LOG_E("Get type blob failed");
45 return ret;
46 }
47 if (memcpy_s(certificateInfo->type, MAX_LEN_SUBJECT_NAME, blob.data, blob.size) != EOK) {
48 CM_LOG_E("copy type failed");
49 return CMR_ERROR_INVALID_OPERATION;
50 }
51
52 ret = CmGetBlobFromBuffer(&blob, outData, offset);
53 if (ret != CM_SUCCESS) {
54 CM_LOG_E("Get keyUri blob failed");
55 return ret;
56 }
57 if (memcpy_s(certificateInfo->keyUri, MAX_LEN_URI, blob.data, blob.size) != EOK) {
58 CM_LOG_E("copy keyUri failed");
59 return CMR_ERROR_INVALID_OPERATION;
60 }
61
62 ret = CmGetBlobFromBuffer(&blob, outData, offset);
63 if (ret != CM_SUCCESS) {
64 CM_LOG_E("Get alias blob failed");
65 return ret;
66 }
67 if (memcpy_s(certificateInfo->alias, MAX_LEN_CERT_ALIAS, blob.data, blob.size) != EOK) {
68 CM_LOG_E("copy alias failed");
69 return CMR_ERROR_INVALID_OPERATION;
70 }
71
72 return ret;
73 }
74
CmAppCertInfoUnpackFromService(const struct CmBlob * outData,struct Credential * certificateInfo)75 static int32_t CmAppCertInfoUnpackFromService(const struct CmBlob *outData, struct Credential *certificateInfo)
76 {
77 uint32_t offset = 0;
78 struct CmBlob blob = { 0, NULL };
79
80 if ((outData == NULL) || (certificateInfo == NULL) || (outData->data == NULL) ||
81 (certificateInfo->credData.data == NULL)) {
82 return CMR_ERROR_NULL_POINTER;
83 }
84
85 int32_t ret = GetUint32FromBuffer(&certificateInfo->isExist, outData, &offset);
86 if (ret != CM_SUCCESS || certificateInfo->isExist == 0) {
87 CM_LOG_E("Get certificateInfo->isExist failed ret:%d, is exist:%u", ret, certificateInfo->isExist);
88 return ret;
89 }
90
91 ret = CmGetAppCertFromBuffer(certificateInfo, outData, &offset);
92 if (ret != CM_SUCCESS) {
93 CM_LOG_E("Get AppCert failed");
94 return ret;
95 }
96
97 ret = GetUint32FromBuffer(&certificateInfo->certNum, outData, &offset);
98 if (ret != CM_SUCCESS) {
99 CM_LOG_E("Get certificateInfo->certNum failed");
100 return ret;
101 }
102
103 ret = GetUint32FromBuffer(&certificateInfo->keyNum, outData, &offset);
104 if (ret != CM_SUCCESS) {
105 CM_LOG_E("Get certificateInfo->keyNum failed");
106 return ret;
107 }
108
109 ret = CmGetBlobFromBuffer(&blob, outData, &offset);
110 if (ret != CM_SUCCESS) {
111 CM_LOG_E("Get certificateInfo->credData failed");
112 return ret;
113 }
114
115 if ((blob.size > certificateInfo->credData.size) || memcpy_s(certificateInfo->credData.data,
116 certificateInfo->credData.size, blob.data, blob.size) != EOK) {
117 CM_LOG_E("copy credData failed");
118 return CMR_ERROR_INVALID_OPERATION;
119 }
120 certificateInfo->credData.size = blob.size;
121
122 return CM_SUCCESS;
123 }
124
GetAppCert(enum CertManagerInterfaceCode type,const struct CmBlob * certUri,const uint32_t store,struct Credential * certificate)125 static int32_t GetAppCert(enum CertManagerInterfaceCode type, const struct CmBlob *certUri, const uint32_t store,
126 struct Credential *certificate)
127 {
128 int32_t ret;
129 struct CmBlob outBlob = { 0, NULL };
130 struct CmParamSet *sendParamSet = NULL;
131
132 struct CmParam params[] = {
133 { .tag = CM_TAG_PARAM0_BUFFER,
134 .blob = *certUri },
135 { .tag = CM_TAG_PARAM0_UINT32,
136 .uint32Param = store },
137 };
138 do {
139 ret = CmParamsToParamSet(params, CM_ARRAY_SIZE(params), &sendParamSet);
140 if (ret != CM_SUCCESS) {
141 CM_LOG_E("GetAppCert CmParamSetPack fail");
142 break;
143 }
144
145 struct CmBlob parcelBlob = {
146 .size = sendParamSet->paramSetSize,
147 .data = (uint8_t *)sendParamSet
148 };
149
150 ret = GetAppCertInitBlob(&outBlob);
151 if (ret != CM_SUCCESS) {
152 CM_LOG_E("GetAppCertInitBlob fail");
153 break;
154 }
155
156 ret = SendRequest(type, &parcelBlob, &outBlob);
157 if (ret != CM_SUCCESS) {
158 CM_LOG_E("GetAppCert request fail");
159 break;
160 }
161
162 ret = CmAppCertInfoUnpackFromService(&outBlob, certificate);
163 if (ret != CM_SUCCESS) {
164 CM_LOG_E("CmAppCertInfoUnpackFromService fail");
165 }
166 } while (0);
167
168 CmFreeParamSet(&sendParamSet);
169 CM_FREE_BLOB(outBlob);
170 return ret;
171 }
172
CmClientGetAppCert(const struct CmBlob * keyUri,const uint32_t store,struct Credential * certificate)173 int32_t CmClientGetAppCert(const struct CmBlob *keyUri, const uint32_t store, struct Credential *certificate)
174 {
175 return GetAppCert(CM_MSG_GET_APP_CERTIFICATE, keyUri, store, certificate);
176 }
177
ClientSerializationAndSend(enum CertManagerInterfaceCode message,struct CmParam * params,uint32_t paramCount,struct CmBlob * outBlob)178 static int32_t ClientSerializationAndSend(enum CertManagerInterfaceCode message, struct CmParam *params,
179 uint32_t paramCount, struct CmBlob *outBlob)
180 {
181 struct CmParamSet *sendParamSet = NULL;
182 int32_t ret = CmParamsToParamSet(params, paramCount, &sendParamSet);
183 if (ret != CM_SUCCESS) {
184 CM_LOG_E("pack params failed, ret = %d", ret);
185 return ret;
186 }
187
188 struct CmBlob parcelBlob = { sendParamSet->paramSetSize, (uint8_t *)sendParamSet };
189 ret = SendRequest(message, &parcelBlob, outBlob);
190 if (ret != CM_SUCCESS) {
191 CM_LOG_E("send request failed, ret = %d", ret);
192 }
193 CmFreeParamSet(&sendParamSet);
194
195 return ret;
196 }
197
CmClientInit(const struct CmBlob * authUri,const struct CmSignatureSpec * spec,struct CmBlob * handle)198 int32_t CmClientInit(const struct CmBlob *authUri, const struct CmSignatureSpec *spec, struct CmBlob *handle)
199 {
200 if (CmCheckBlob(authUri) != CM_SUCCESS || CmCheckBlob(handle) != CM_SUCCESS) {
201 CM_LOG_E("invalid handle or inData");
202 return CMR_ERROR_INVALID_ARGUMENT;
203 }
204
205 struct CmBlob signSpec = { sizeof(struct CmSignatureSpec), (uint8_t *)spec };
206 struct CmParam params[] = {
207 { .tag = CM_TAG_PARAM0_BUFFER, .blob = *authUri },
208 { .tag = CM_TAG_PARAM1_BUFFER, .blob = signSpec },
209 };
210
211 int32_t ret = ClientSerializationAndSend(CM_MSG_INIT, params, CM_ARRAY_SIZE(params), handle);
212 if (ret != CM_SUCCESS) {
213 CM_LOG_E("update serialization and send failed, ret = %d", ret);
214 }
215 return ret;
216 }
217
CmClientUpdate(const struct CmBlob * handle,const struct CmBlob * inData)218 int32_t CmClientUpdate(const struct CmBlob *handle, const struct CmBlob *inData)
219 {
220 if (CmCheckBlob(handle) != CM_SUCCESS || CmCheckBlob(inData) != CM_SUCCESS) {
221 CM_LOG_E("invalid handle or inData");
222 return CMR_ERROR_INVALID_ARGUMENT;
223 }
224
225 struct CmParam params[] = {
226 { .tag = CM_TAG_PARAM0_BUFFER, .blob = *handle },
227 { .tag = CM_TAG_PARAM1_BUFFER, .blob = *inData },
228 };
229
230 struct CmBlob outBlob = { 0, NULL };
231 int32_t ret = ClientSerializationAndSend(CM_MSG_UPDATE, params, CM_ARRAY_SIZE(params), &outBlob);
232 if (ret != CM_SUCCESS) {
233 CM_LOG_E("update serialization and send failed, ret = %d", ret);
234 }
235 return ret;
236 }
237
CmClientFinish(const struct CmBlob * handle,const struct CmBlob * inData,struct CmBlob * outData)238 int32_t CmClientFinish(const struct CmBlob *handle, const struct CmBlob *inData, struct CmBlob *outData)
239 {
240 if (CmCheckBlob(handle) != CM_SUCCESS) { /* finish: inData and outData can be {0, NULL} */
241 CM_LOG_E("invalid handle");
242 return CMR_ERROR_INVALID_ARGUMENT;
243 }
244
245 struct CmParam params[] = {
246 { .tag = CM_TAG_PARAM0_BUFFER, .blob = *handle },
247 { .tag = CM_TAG_PARAM1_BUFFER, .blob = *inData },
248 };
249
250 int32_t ret = ClientSerializationAndSend(CM_MSG_FINISH, params, CM_ARRAY_SIZE(params), outData);
251 if (ret != CM_SUCCESS) {
252 CM_LOG_E("finish serialization and send failed, ret = %d", ret);
253 }
254 return ret;
255 }
256
CmClientAbort(const struct CmBlob * handle)257 int32_t CmClientAbort(const struct CmBlob *handle)
258 {
259 if (CmCheckBlob(handle) != CM_SUCCESS) {
260 CM_LOG_E("invalid handle");
261 return CMR_ERROR_INVALID_ARGUMENT;
262 }
263
264 struct CmParam params[] = {
265 { .tag = CM_TAG_PARAM0_BUFFER, .blob = *handle },
266 };
267
268 struct CmBlob outBlob = { 0, NULL };
269 int32_t ret = ClientSerializationAndSend(CM_MSG_ABORT, params, CM_ARRAY_SIZE(params), &outBlob);
270 if (ret != CM_SUCCESS) {
271 CM_LOG_E("abort serialization and send failed, ret = %d", ret);
272 }
273 return ret;
274 }
275
276