1 /*
2 * Copyright (c) 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 "cm_ipc_client_serialization.h"
17
18 #include "cm_log.h"
19 #include "cm_mem.h"
20
21 #include "cm_param.h"
22 #include "cm_x509.h"
23
GetUint32FromBuffer(uint32_t * value,const struct CmBlob * srcBlob,uint32_t * srcOffset)24 int32_t GetUint32FromBuffer(uint32_t *value, const struct CmBlob *srcBlob, uint32_t *srcOffset)
25 {
26 if ((*srcOffset > srcBlob->size) || (srcBlob->size - *srcOffset < sizeof(uint32_t))) {
27 return CMR_ERROR_BUFFER_TOO_SMALL;
28 }
29
30 if (memcpy_s(value, sizeof(uint32_t), srcBlob->data + *srcOffset, sizeof(uint32_t)) != EOK) {
31 return CMR_ERROR_INVALID_OPERATION;
32 }
33
34 *srcOffset += sizeof(uint32_t);
35 return CM_SUCCESS;
36 }
37
CmGetBlobFromBuffer(struct CmBlob * blob,const struct CmBlob * srcBlob,uint32_t * srcOffset)38 int32_t CmGetBlobFromBuffer(struct CmBlob *blob, const struct CmBlob *srcBlob, uint32_t *srcOffset)
39 {
40 if ((*srcOffset > srcBlob->size) || ((srcBlob->size - *srcOffset) < sizeof(uint32_t))) {
41 return CMR_ERROR_BUFFER_TOO_SMALL;
42 }
43
44 uint32_t size = *((uint32_t *)(srcBlob->data + *srcOffset));
45 if (ALIGN_SIZE(size) > srcBlob->size - *srcOffset - sizeof(uint32_t)) {
46 return CMR_ERROR_BUFFER_TOO_SMALL;
47 }
48
49 blob->size = size;
50 *srcOffset += sizeof(blob->size);
51 blob->data = (uint8_t *)(srcBlob->data + *srcOffset);
52 *srcOffset += ALIGN_SIZE(blob->size);
53 return CM_SUCCESS;
54 }
55
CmCertListGetCertCount(const struct CmBlob * outData,struct CertList * certificateList,uint32_t * offset)56 static int32_t CmCertListGetCertCount(const struct CmBlob *outData, struct CertList *certificateList,
57 uint32_t *offset)
58 {
59 uint32_t certsCount = 0;
60 int32_t ret = GetUint32FromBuffer(&certsCount, outData, offset);
61 if (ret != CM_SUCCESS) {
62 CM_LOG_E("Get certificateList->certsCount failed");
63 return ret;
64 }
65
66 if (certsCount > certificateList->certsCount) {
67 CM_LOG_E("Caller Buffer too small");
68 return CMR_ERROR_BUFFER_TOO_SMALL;
69 }
70 certificateList->certsCount = certsCount;
71
72 return CM_SUCCESS;
73 }
74
CmCertificateListUnpackFromService(const struct CmBlob * outData,struct CertList * certificateList)75 int32_t CmCertificateListUnpackFromService(const struct CmBlob *outData, struct CertList *certificateList)
76 {
77 if (CmCheckBlob(outData) != CM_SUCCESS || (certificateList == NULL) || (certificateList->certAbstract == NULL)) {
78 return CMR_ERROR_NULL_POINTER;
79 }
80
81 uint32_t offset = 0;
82 int32_t ret = CmCertListGetCertCount(outData, certificateList, &offset);
83 if (ret != CM_SUCCESS) {
84 CM_LOG_E("Get Cert list count failed");
85 return ret;
86 }
87
88 for (uint32_t i = 0; i < certificateList->certsCount; i++) {
89 struct CmBlob blob = { 0, NULL };
90 ret = CmGetBlobFromBuffer(&blob, outData, &offset);
91 if (ret != CM_SUCCESS) {
92 CM_LOG_E("Get subjectNameBlob FromBuffer failed");
93 return ret;
94 }
95 if (memcpy_s(certificateList->certAbstract[i].subjectName, MAX_LEN_SUBJECT_NAME, blob.data, blob.size) != EOK) {
96 CM_LOG_E("copy subjectName failed");
97 return CMR_ERROR_INVALID_OPERATION;
98 }
99
100 uint32_t status = 0;
101 ret = GetUint32FromBuffer(&status, outData, &offset);
102 if (ret != CM_SUCCESS) {
103 CM_LOG_E("get status failed");
104 return ret;
105 }
106 certificateList->certAbstract[i].status = (status >= 1) ? false : true;
107
108 ret = CmGetBlobFromBuffer(&blob, outData, &offset);
109 if (ret != CM_SUCCESS) {
110 CM_LOG_E("get uri failed");
111 return ret;
112 }
113 if (memcpy_s(certificateList->certAbstract[i].uri, MAX_LEN_URI, blob.data, blob.size) != EOK) {
114 CM_LOG_E("copy uri failed");
115 return CMR_ERROR_INVALID_OPERATION;
116 }
117
118 ret = CmGetBlobFromBuffer(&blob, outData, &offset);
119 if (ret != CM_SUCCESS) {
120 CM_LOG_E("get certAlias failed");
121 return ret;
122 }
123 if (memcpy_s(certificateList->certAbstract[i].certAlias, MAX_LEN_CERT_ALIAS, blob.data, blob.size) != EOK) {
124 CM_LOG_E("copy certAlias failed");
125 return CMR_ERROR_INVALID_OPERATION;
126 }
127 }
128 return CM_SUCCESS;
129 }
130
GetInfoFromX509Cert(X509 * x509cert,struct CertInfo * cInfo)131 static int32_t GetInfoFromX509Cert(X509 *x509cert, struct CertInfo *cInfo)
132 {
133 int32_t subjectNameLen = GetX509SubjectNameLongFormat(x509cert, cInfo->subjectName, MAX_LEN_SUBJECT_NAME);
134 if (subjectNameLen <= 0) {
135 CM_LOG_E("get cert subjectName failed");
136 return CM_FAILURE;
137 }
138
139 int32_t issuerNameLen = GetX509IssueNameLongFormat(x509cert, cInfo->issuerName, MAX_LEN_ISSUER_NAME);
140 if (issuerNameLen <= 0) {
141 CM_LOG_E("get cert issuerName failed");
142 return CM_FAILURE;
143 }
144
145 int32_t serialLen = GetX509SerialNumber(x509cert, cInfo->serial, MAX_LEN_SERIAL);
146 if (serialLen <= 0) {
147 CM_LOG_E("get cert serial failed");
148 return CM_FAILURE;
149 }
150
151 int32_t notBeforeLen = GetX509NotBefore(x509cert, cInfo->notBefore, MAX_LEN_NOT_BEFORE);
152 if (notBeforeLen <= 0) {
153 CM_LOG_E("get cert notBefore failed");
154 return CM_FAILURE;
155 }
156
157 int32_t notAfterLen = GetX509NotAfter(x509cert, cInfo->notAfter, MAX_LEN_NOT_AFTER);
158 if (notAfterLen <= 0) {
159 CM_LOG_E("get cert notAfter failed");
160 return CM_FAILURE;
161 }
162
163 int32_t fingerprintLen = GetX509Fingerprint(x509cert, cInfo->fingerprintSha256, MAX_LEN_FINGER_PRINT_SHA256);
164 if (fingerprintLen <= 0) {
165 CM_LOG_E("get cert fingerprintSha256 failed");
166 return CM_FAILURE;
167 }
168 return CM_SUCCESS;
169 }
170
GetInfoFromCertData(struct CertInfo * cInfo)171 static int32_t GetInfoFromCertData(struct CertInfo *cInfo)
172 {
173 X509 *cert = InitCertContext(cInfo->certInfo.data, cInfo->certInfo.size);
174 if (cert == NULL) {
175 CM_LOG_E("Parse X509 cert fail");
176 return CMR_ERROR_INVALID_CERT_FORMAT;
177 }
178
179 int32_t ret = GetInfoFromX509Cert(cert, cInfo);
180 if (ret != CM_SUCCESS) {
181 CM_LOG_E("failed get cert info from x509 cert");
182 FreeCertContext(cert);
183 return ret;
184 }
185
186 FreeCertContext(cert);
187 return CM_SUCCESS;
188 }
189
CmCertificateInfoUnpackFromService(const struct CmBlob * outData,const struct CmBlob * certUri,struct CertInfo * cInfo)190 int32_t CmCertificateInfoUnpackFromService(const struct CmBlob *outData, const struct CmBlob *certUri,
191 struct CertInfo *cInfo)
192 {
193 if (CmCheckBlob(&(cInfo->certInfo))) {
194 return CMR_ERROR_INVALID_ARGUMENT;
195 }
196
197 struct CmBlob bufBlob = { 0, NULL };
198 uint32_t offset = 0;
199 int32_t ret = CmGetBlobFromBuffer(&bufBlob, outData, &offset);
200 if (ret != CM_SUCCESS) {
201 CM_LOG_E("get cert data faild");
202 return ret;
203 }
204 if (memcpy_s(cInfo->certInfo.data, cInfo->certInfo.size, bufBlob.data, bufBlob.size) != EOK) {
205 CM_LOG_E("copy cert data failed");
206 return CMR_ERROR_INVALID_OPERATION;
207 }
208 cInfo->certInfo.size = bufBlob.size;
209
210 ret = GetInfoFromCertData(cInfo);
211 if (ret != CM_SUCCESS) {
212 return ret;
213 }
214
215 uint32_t status = 0;
216 ret = GetUint32FromBuffer(&(status), outData, &offset);
217 if (ret != CM_SUCCESS) {
218 CM_LOG_E("copy status failed");
219 return ret;
220 }
221 cInfo->status = (status >= 1) ? false : true;
222
223 ret = CmGetBlobFromBuffer(&bufBlob, outData, &offset);
224 if (ret != CM_SUCCESS) {
225 return ret;
226 }
227
228 (void)memset_s(cInfo->certAlias, MAX_LEN_CERT_ALIAS, 0, MAX_LEN_CERT_ALIAS);
229 if (memcpy_s(cInfo->certAlias, MAX_LEN_CERT_ALIAS, bufBlob.data, bufBlob.size) != EOK) {
230 CM_LOG_E("copy alias failed");
231 return CMR_ERROR_INVALID_OPERATION;
232 }
233
234 (void)memset_s(cInfo->uri, MAX_LEN_URI, 0, MAX_LEN_URI); /* uri */
235 if (memcpy_s(cInfo->uri, MAX_LEN_URI, certUri->data, certUri->size) != EOK) {
236 CM_LOG_E("copy uri failed");
237 return CMR_ERROR_INVALID_OPERATION;
238 }
239 return CM_SUCCESS;
240 }
241
CmParamsToParamSet(struct CmParam * params,uint32_t cnt,struct CmParamSet ** outParamSet)242 int32_t CmParamsToParamSet(struct CmParam *params, uint32_t cnt, struct CmParamSet **outParamSet)
243 {
244 struct CmParamSet *newParamSet = NULL;
245
246 int32_t ret = CmInitParamSet(&newParamSet);
247 if (ret != CM_SUCCESS) {
248 CM_LOG_E("init param set failed");
249 return ret;
250 }
251
252 do {
253 uint8_t tmpData = 0;
254 struct CmBlob tmpBlob = { sizeof(tmpData), &tmpData };
255 for (uint32_t i = 0; i < cnt; ++i) {
256 if ((GetTagType(params[i].tag) == CM_TAG_TYPE_BYTES) &&
257 (params[i].blob.size == 0 || params[i].blob.data == NULL)) {
258 params[i].tag += CM_PARAM_BUFFER_NULL_INTERVAL;
259 params[i].blob = tmpBlob;
260 }
261 }
262
263 ret = CmAddParams(newParamSet, params, cnt);
264 if (ret != CM_SUCCESS) {
265 CM_LOG_E("add in params failed");
266 break;
267 }
268
269 ret = CmBuildParamSet(&newParamSet);
270 if (ret != CM_SUCCESS) {
271 CM_LOG_E("build paramset failed!");
272 break;
273 }
274 } while (0);
275 if (ret != CM_SUCCESS) {
276 CmFreeParamSet(&newParamSet);
277 return ret;
278 }
279
280 *outParamSet = newParamSet;
281
282 return ret;
283 }
284