• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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