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