1 /*
2  * Copyright (c) 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 "cf_param.h"
17 
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include "securec.h"
23 
24 #include "cf_log.h"
25 #include "cf_memory.h"
26 #include "cf_result.h"
27 
CfGetTagType(CfTag tag)28 CfTagType CfGetTagType(CfTag tag)
29 {
30     return (CfTagType)((uint32_t)tag & CF_TAG_TYPE_MASK);
31 }
32 
CfInitParamSet(CfParamSet ** paramSet)33 int32_t CfInitParamSet(CfParamSet **paramSet)
34 {
35     if (paramSet == NULL) {
36         CF_LOG_E("invalid init params!");
37         return CF_NULL_POINTER;
38     }
39 
40     *paramSet = (CfParamSet *)CfMalloc(CF_DEFAULT_PARAM_SET_SIZE, 0);
41     if (*paramSet == NULL) {
42         CF_LOG_E("malloc init param set failed!");
43         return CF_ERR_MALLOC;
44     }
45     (*paramSet)->paramsCnt = 0;
46     (*paramSet)->paramSetSize = sizeof(CfParamSet);
47     return CF_SUCCESS;
48 }
49 
CfCheckParamSet(const CfParamSet * paramSet,uint32_t size)50 static int32_t CfCheckParamSet(const CfParamSet *paramSet, uint32_t size)
51 {
52     if ((size < sizeof(CfParamSet)) || (size > CF_PARAM_SET_MAX_SIZE) ||
53         (paramSet->paramSetSize != size) ||
54         (paramSet->paramsCnt > ((size - sizeof(CfParamSet)) / sizeof(CfParam)))) {
55         CF_LOG_E("invalid param set!");
56         return CF_INVALID_PARAMS;
57     }
58     return CF_SUCCESS;
59 }
60 
CfFreshParamSet(CfParamSet * paramSet,bool isCopy)61 static int32_t CfFreshParamSet(CfParamSet *paramSet, bool isCopy)
62 {
63     int32_t ret = CfCheckParamSet(paramSet, paramSet->paramSetSize);
64     if (ret != CF_SUCCESS) {
65         CF_LOG_E("invalid fresh paramSet");
66         return ret;
67     }
68 
69     uint32_t size = paramSet->paramSetSize;
70     uint32_t offset = sizeof(CfParamSet) + sizeof(CfParam) * paramSet->paramsCnt;
71 
72     for (uint32_t i = 0; i < paramSet->paramsCnt; i++) {
73         if (offset > size) {
74             CF_LOG_E("invalid param set offset!");
75             return CF_INVALID_PARAMS;
76         }
77         if (CfGetTagType(paramSet->params[i].tag) == CF_TAG_TYPE_BYTES) {
78             if (CfIsAdditionOverflow(offset, paramSet->params[i].blob.size)) {
79                 CF_LOG_E("blob size overflow!");
80                 return CF_INVALID_PARAMS;
81             }
82 
83             if (isCopy && (memcpy_s((uint8_t *)paramSet + offset, size - offset,
84                 paramSet->params[i].blob.data, paramSet->params[i].blob.size) != EOK)) {
85                 CF_LOG_E("copy param blob failed!");
86                 return CF_ERR_COPY;
87             }
88             paramSet->params[i].blob.data = (uint8_t *)paramSet + offset;
89             offset += paramSet->params[i].blob.size;
90         }
91     }
92 
93     if (paramSet->paramSetSize != offset) {
94         CF_LOG_E("invalid param set size!");
95         return CF_INVALID_PARAMS;
96     }
97     return CF_SUCCESS;
98 }
99 
BuildParamSet(CfParamSet ** paramSet)100 static int32_t BuildParamSet(CfParamSet **paramSet)
101 {
102     CfParamSet *freshParamSet = *paramSet;
103     uint32_t size = freshParamSet->paramSetSize;
104     uint32_t offset = sizeof(CfParamSet) + sizeof(CfParam) * freshParamSet->paramsCnt;
105 
106     if (size > CF_DEFAULT_PARAM_SET_SIZE) {
107         freshParamSet = (CfParamSet *)CfMalloc(size, 0);
108         if (freshParamSet == NULL) {
109             CF_LOG_E("malloc params failed!");
110             return CF_ERR_MALLOC;
111         }
112         if (memcpy_s(freshParamSet, size, *paramSet, offset) != EOK) {
113             CF_FREE_PTR(freshParamSet);
114             CF_LOG_E("copy params failed!");
115             return CF_ERR_COPY;
116         }
117         CF_FREE_PTR(*paramSet);
118         *paramSet = freshParamSet;
119     }
120 
121     return CfFreshParamSet(freshParamSet, true);
122 }
123 
CfBuildParamSet(CfParamSet ** paramSet)124 int32_t CfBuildParamSet(CfParamSet **paramSet)
125 {
126     if ((paramSet == NULL) || (*paramSet == NULL)) {
127         return CF_NULL_POINTER;
128     }
129 
130     int ret = CfCheckParamSet(*paramSet, (*paramSet)->paramSetSize);
131     if (ret != CF_SUCCESS) {
132         CF_LOG_E("invalid build params!");
133         return ret;
134     }
135 
136     return BuildParamSet(paramSet);
137 }
138 
CfFreeParamSet(CfParamSet ** paramSet)139 void CfFreeParamSet(CfParamSet **paramSet)
140 {
141     if (paramSet == NULL) {
142         CF_LOG_E("invalid free paramset!");
143         return;
144     }
145     CF_FREE_PTR(*paramSet);
146 }
147 
CfGetParam(const CfParamSet * paramSet,uint32_t tag,CfParam ** param)148 int32_t CfGetParam(const CfParamSet *paramSet, uint32_t tag, CfParam **param)
149 {
150     if ((paramSet == NULL) || (param == NULL)) {
151         CF_LOG_E("invalid params!");
152         return CF_NULL_POINTER;
153     }
154 
155     if (CfCheckParamSet(paramSet, paramSet->paramSetSize) != CF_SUCCESS) {
156         CF_LOG_E("invalid paramSet!");
157         return CF_INVALID_PARAMS;
158     }
159 
160     for (uint32_t i = 0; i < paramSet->paramsCnt; i++) {
161         if (tag == paramSet->params[i].tag) {
162             *param = (CfParam *)&paramSet->params[i];
163             return CF_SUCCESS;
164         }
165     }
166 
167     return CF_NOT_EXIST;
168 }
169 
CheckBeforeAddParams(const CfParamSet * paramSet,const CfParam * params,uint32_t paramCnt)170 static int32_t CheckBeforeAddParams(const CfParamSet *paramSet, const CfParam *params,
171     uint32_t paramCnt)
172 {
173     if ((params == NULL) || (paramSet == NULL) || (paramSet->paramSetSize > CF_PARAM_SET_MAX_SIZE) ||
174         (paramCnt > CF_DEFAULT_PARAM_CNT) || ((paramSet->paramsCnt + paramCnt) > CF_DEFAULT_PARAM_CNT)) {
175         CF_LOG_E("invalid params or paramset!");
176         return CF_INVALID_PARAMS;
177     }
178 
179     for (uint32_t i = 0; i < paramCnt; i++) {
180         if ((CfGetTagType(params[i].tag) == CF_TAG_TYPE_BYTES) &&
181             ((params[i].blob.data == NULL) || (params[i].blob.size == 0))) {
182             CF_LOG_E("invalid blob param!");
183             return CF_INVALID_PARAMS;
184         }
185     }
186     return CF_SUCCESS;
187 }
188 
CfAddParams(CfParamSet * paramSet,const CfParam * params,uint32_t paramCnt)189 int32_t CfAddParams(CfParamSet *paramSet, const CfParam *params, uint32_t paramCnt)
190 {
191     int32_t ret = CheckBeforeAddParams(paramSet, params, paramCnt);
192     if (ret != CF_SUCCESS) {
193         return ret;
194     }
195 
196     for (uint32_t i = 0; i < paramCnt; i++) {
197         if (paramSet->paramSetSize > CF_PARAM_SET_MAX_SIZE) {
198             CF_LOG_E("params size[%u] too large!", paramSet->paramSetSize);
199             return CF_INVALID_PARAMS;
200         }
201         paramSet->paramSetSize += sizeof(CfParam);
202         if (CfGetTagType(params[i].tag) == CF_TAG_TYPE_BYTES) {
203             if (CfIsAdditionOverflow(paramSet->paramSetSize, params[i].blob.size)) {
204                 CF_LOG_E("params size overflow!");
205                 paramSet->paramSetSize -= sizeof(CfParam);
206                 return CF_INVALID_PARAMS;
207             }
208             paramSet->paramSetSize += params[i].blob.size;
209         }
210         (void)memcpy_s(&paramSet->params[paramSet->paramsCnt++], sizeof(CfParam), &params[i], sizeof(CfParam));
211     }
212     return CF_SUCCESS;
213 }
214