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_object_extension.h"
17 
18 #include "securec.h"
19 
20 #include "cf_ability.h"
21 #include "cf_log.h"
22 #include "cf_magic.h"
23 #include "cf_memory.h"
24 #include "cf_param.h"
25 #include "cf_param_parse.h"
26 #include "cf_result.h"
27 
28 #include "cf_extension_adapter_ability_define.h"
29 
30 typedef struct {
31     CfBase base;
32     CfExtensionAdapterAbilityFunc func;
33     CfBase *adapterRes;
34 } CfExtensionObjStruct;
35 
CfExtensionCreate(const CfEncodingBlob * in,CfBase ** obj)36 int32_t CfExtensionCreate(const CfEncodingBlob *in, CfBase **obj)
37 {
38     if ((in == NULL) || (obj == NULL)) {
39         CF_LOG_E("param null");
40         return CF_NULL_POINTER;
41     }
42 
43     CfExtensionAdapterAbilityFunc *func = (CfExtensionAdapterAbilityFunc *)GetAbility(
44         CF_ABILITY(CF_ABILITY_TYPE_ADAPTER, CF_OBJ_TYPE_EXTENSION));
45     if ((func == NULL) || (func->base.type != CF_MAGIC(CF_MAGIC_TYPE_ADAPTER_FUNC, CF_OBJ_TYPE_EXTENSION))) {
46         CF_LOG_E("invalid func type");
47         return CF_INVALID_PARAMS;
48     }
49 
50     CfExtensionObjStruct *tmp = CfMalloc(sizeof(CfExtensionObjStruct), 0);
51     if (tmp == NULL) {
52         CF_LOG_E("malloc cert obj failed");
53         return CF_ERR_MALLOC;
54     }
55 
56     tmp->base.type = CF_MAGIC(CF_MAGIC_TYPE_OBJ_RESOURCE, CF_OBJ_TYPE_EXTENSION);
57     int32_t ret = func->adapterCreate(in, &tmp->adapterRes);
58     if (ret != CF_SUCCESS) {
59         CF_LOG_E("cert adapter create failed");
60         CfFree(tmp);
61         return ret;
62     }
63     (void)memcpy_s(&tmp->func, sizeof(CfExtensionAdapterAbilityFunc), func, sizeof(CfExtensionAdapterAbilityFunc));
64 
65     *obj = &(tmp->base);
66     return CF_SUCCESS;
67 }
68 
CfExtGetItem(const CfExtensionObjStruct * obj,const CfParamSet * in,CfParamSet ** out)69 static int32_t CfExtGetItem(const CfExtensionObjStruct *obj, const CfParamSet *in, CfParamSet **out)
70 {
71     CfParam *tmpParam = NULL;
72     int32_t ret = CfGetParam(in, CF_TAG_PARAM0_INT32, &tmpParam);
73     if (ret != CF_SUCCESS) {
74         CF_LOG_E("ext get item failed, ret = %d", ret);
75         return ret;
76     }
77 
78     CfBlob itemRes = { 0, NULL };
79     ret = obj->func.adapterGetItem(obj->adapterRes, (CfItemId)tmpParam->int32Param, &itemRes);
80     if (ret != CF_SUCCESS) {
81         CF_LOG_E("ext adapter get item failed, ret = %d", ret);
82         return ret;
83     }
84 
85     CfParam params[] = {
86         { .tag = CF_TAG_RESULT_TYPE, .int32Param = CF_TAG_TYPE_BYTES },
87         { .tag = CF_TAG_RESULT_BYTES, .blob = itemRes },
88     };
89     ret = CfConstructParamSetOut(params, sizeof(params) / sizeof(CfParam), out);
90     CfFree(itemRes.data);
91     return ret;
92 }
93 
CfExtGetOids(const CfExtensionObjStruct * obj,const CfParamSet * in,CfParamSet ** out)94 static int32_t CfExtGetOids(const CfExtensionObjStruct *obj, const CfParamSet *in, CfParamSet **out)
95 {
96     CfParam *oidTypeParam = NULL;
97     int32_t ret = CfGetParam(in, CF_TAG_PARAM0_INT32, &oidTypeParam);
98     if (ret != CF_SUCCESS) {
99         CF_LOG_E("get oid type failed, ret = %d", ret);
100         return ret;
101     }
102 
103     CfBlobArray oids = { NULL, 0 };
104     ret = obj->func.adapterGetOids(obj->adapterRes, (CfExtensionOidType)oidTypeParam->int32Param, &oids);
105     if (ret != CF_SUCCESS) {
106         CF_LOG_E("adapter get oids failed, ret = %d", ret);
107         return ret;
108     }
109 
110     ret = CfConstructArrayParamSetOut(&oids, out);
111     FreeCfBlobArray(oids.data, oids.count);
112     return ret;
113 }
114 
CfExtGetEntry(const CfExtensionObjStruct * obj,const CfParamSet * in,CfParamSet ** out)115 static int32_t CfExtGetEntry(const CfExtensionObjStruct *obj, const CfParamSet *in, CfParamSet **out)
116 {
117     CfParam *entryTypeParam = NULL;
118     int32_t ret = CfGetParam(in, CF_TAG_PARAM0_INT32, &entryTypeParam);
119     if (ret != CF_SUCCESS) {
120         CF_LOG_E("get entry type failed, ret = %d", ret);
121         return ret;
122     }
123 
124     CfParam *oidParam = NULL;
125     ret = CfGetParam(in, CF_TAG_PARAM1_BUFFER, &oidParam);
126     if (ret != CF_SUCCESS) {
127         CF_LOG_E("get oid failed, ret = %d", ret);
128         return ret;
129     }
130 
131     CfBlob entryValue = { 0, NULL };
132     ret = obj->func.adapterGetEntry(obj->adapterRes, (CfExtensionEntryType)entryTypeParam->int32Param,
133         &oidParam->blob, &entryValue);
134     if (ret != CF_SUCCESS) {
135         CF_LOG_E("adapter get entry failed, ret = %d", ret);
136         return ret;
137     }
138 
139     CfParam params[] = {
140         { .tag = CF_TAG_RESULT_TYPE, .int32Param = CF_TAG_TYPE_BYTES },
141         { .tag = CF_TAG_RESULT_BYTES, .blob = entryValue },
142     };
143     ret = CfConstructParamSetOut(params, sizeof(params) / sizeof(CfParam), out);
144     CfFree(entryValue.data);
145     return ret;
146 }
147 
CfExtensionGet(const CfBase * obj,const CfParamSet * in,CfParamSet ** out)148 int32_t CfExtensionGet(const CfBase *obj, const CfParamSet *in, CfParamSet **out)
149 {
150     if ((obj == NULL) || (in == NULL) || (out == NULL)) {
151         CF_LOG_E("cfextensionget params is null");
152         return CF_NULL_POINTER;
153     }
154 
155     CfExtensionObjStruct *tmp = (CfExtensionObjStruct *)obj;
156     if (tmp->base.type != CF_MAGIC(CF_MAGIC_TYPE_OBJ_RESOURCE, CF_OBJ_TYPE_EXTENSION)) {
157         CF_LOG_E("invalid resource type");
158         return CF_INVALID_PARAMS;
159     }
160 
161     CfParam *tmpParam = NULL;
162     int32_t ret = CfGetParam(in, CF_TAG_GET_TYPE, &tmpParam);
163     if (ret != CF_SUCCESS) {
164         CF_LOG_E("get type failed, ret = %d", ret);
165         return ret;
166     }
167 
168     switch (tmpParam->int32Param) {
169         case CF_GET_TYPE_EXT_ITEM:
170             return CfExtGetItem(tmp, in, out);
171         case CF_GET_TYPE_EXT_OIDS:
172             return CfExtGetOids(tmp, in, out);
173         case CF_GET_TYPE_EXT_ENTRY:
174             return CfExtGetEntry(tmp, in, out);
175         default:
176             CF_LOG_E("extension get type invalid, type = %d", tmpParam->int32Param);
177             return CF_NOT_SUPPORT;
178     }
179 }
180 
CfExtensionCheck(const CfBase * obj,const CfParamSet * in,CfParamSet ** out)181 int32_t CfExtensionCheck(const CfBase *obj, const CfParamSet *in, CfParamSet **out)
182 {
183     if ((obj == NULL) || (in == NULL) || (out == NULL)) {
184         CF_LOG_E("cfextensioncheck params is null");
185         return CF_NULL_POINTER;
186     }
187 
188     CfExtensionObjStruct *tmp = (CfExtensionObjStruct *)obj;
189     if (tmp->base.type != CF_MAGIC(CF_MAGIC_TYPE_OBJ_RESOURCE, CF_OBJ_TYPE_EXTENSION)) {
190         CF_LOG_E("invalid resource type");
191         return CF_INVALID_PARAMS;
192     }
193 
194     CfParam *tmpParam = NULL;
195     int32_t ret = CfGetParam(in, CF_TAG_CHECK_TYPE, &tmpParam);
196     if (ret != CF_SUCCESS) {
197         CF_LOG_E("get check type failed, ret = %d", ret);
198         return ret;
199     }
200 
201     if (tmpParam->int32Param == CF_CHECK_TYPE_EXT_CA) {
202         int32_t pathLen;
203         ret = tmp->func.adapterCheckCA(tmp->adapterRes, &pathLen);
204         if (ret != CF_SUCCESS) {
205             CF_LOG_E("adapter check ca failed");
206             return ret;
207         }
208 
209         CfParam params[] = {
210             { .tag = CF_TAG_RESULT_TYPE, .int32Param = CF_TAG_TYPE_INT },
211             { .tag = CF_TAG_RESULT_INT, .int32Param = pathLen },
212         };
213         return CfConstructParamSetOut(params, sizeof(params) / sizeof(CfParam), out);
214     } else if (tmpParam->int32Param == CF_CHECK_TYPE_EXT_HAS_UN_SUPPORT) {
215         bool flag = false;
216         ret = tmp->func.adapterHasUnsupportedCriticalExtension(tmp->adapterRes, &flag);
217         if (ret != CF_SUCCESS) {
218             CF_LOG_E("adapter has unsupported critical extension failed");
219             return ret;
220         }
221         CfParam params[] = {
222             { .tag = CF_TAG_RESULT_TYPE, .int32Param = CF_TAG_TYPE_BOOL },
223             { .tag = CF_TAG_RESULT_BOOL, .boolParam = flag },
224         };
225         return CfConstructParamSetOut(params, sizeof(params) / sizeof(CfParam), out);
226     }
227 
228     CF_LOG_E("extension check type invalid, type = %d", tmpParam->int32Param);
229     return CF_NOT_SUPPORT;
230 }
231 
CfExtensionDestroy(CfBase ** obj)232 void CfExtensionDestroy(CfBase **obj)
233 {
234     if ((obj == NULL) || (*obj == NULL)) {
235         return;
236     }
237 
238     CfExtensionObjStruct *tmp = (CfExtensionObjStruct *)*obj;
239     if (tmp->base.type != CF_MAGIC(CF_MAGIC_TYPE_OBJ_RESOURCE, CF_OBJ_TYPE_EXTENSION)) {
240         /* only extension objects can be destroyed */
241         CF_LOG_E("invalid resource type");
242         return;
243     }
244 
245     tmp->func.adapterDestory(&tmp->adapterRes);
246     CfFree(tmp);
247     *obj = NULL;
248     return;
249 }