• 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 "cert_manager_session_mgr.h"
17 #include "cert_manager_mem.h"
18 #include "cm_log.h"
19 
20 #include <pthread.h>
21 #include <stdio.h>
22 
23 #include "hks_api.h"
24 #include "hks_param.h"
25 #include "hks_type.h"
26 
27 #include "securec.h"
28 
29 #define MAX_OPERATIONS_COUNT 15
30 
31 static struct DoubleList g_sessionList = { &g_sessionList, &g_sessionList };
32 static uint32_t g_sessionCount = 0;
33 static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
34 
35 // LCOV_EXCL_START
DeleteHuksInitInfo(const struct CmBlob * handle)36 static void DeleteHuksInitInfo(const struct CmBlob *handle)
37 {
38     struct HksParamSet *paramSet = NULL;
39     if (HksInitParamSet(&paramSet) != HKS_SUCCESS) {
40         return;
41     }
42 
43     (void)HksAbort((const struct HksBlob *)handle, paramSet);
44     HksFreeParamSet(&paramSet);
45 }
46 
FreeSessionNode(struct CmSessionNode ** node)47 static void FreeSessionNode(struct CmSessionNode **node)
48 {
49     if ((node == NULL) || (*node == NULL)) {
50         return;
51     }
52 
53     CM_FREE_PTR((*node)->handle.data);
54     CM_FREE_PTR((*node)->info.uri.data);
55     CM_FREE_PTR(*node);
56 }
57 
58 /* Need to lock before calling RemoveAndFreeSessionNode */
RemoveAndFreeSessionNode(struct CmSessionNode ** sessionNode)59 static void RemoveAndFreeSessionNode(struct CmSessionNode **sessionNode)
60 {
61     if ((sessionNode == NULL) || (*sessionNode == NULL)) {
62         return;
63     }
64 
65     CmRemoveNodeFromList(&(*sessionNode)->listHead);
66     FreeSessionNode(sessionNode);
67 }
68 
69 /* Need to lock before calling DeleteFirstAbortableSession */
DeleteFirstAbortableSession(void)70 static int32_t DeleteFirstAbortableSession(void)
71 {
72     struct CmSessionNode *sessionNode = NULL;
73 
74     CM_DLIST_ITER(sessionNode, &g_sessionList) {
75         if (sessionNode->abortable) {
76             DeleteHuksInitInfo(&(sessionNode->handle));
77             RemoveAndFreeSessionNode(&sessionNode);
78             --g_sessionCount;
79             CM_LOG_D("delete session count: %u", g_sessionCount);
80             return CM_SUCCESS;
81         }
82     }
83 
84     return CMR_ERROR_NOT_FOUND;
85 }
86 
AddSessionNode(struct CmSessionNode * sessionNode)87 static int32_t AddSessionNode(struct CmSessionNode *sessionNode)
88 {
89     pthread_mutex_lock(&g_lock);
90 
91     if (g_sessionCount >= MAX_OPERATIONS_COUNT) {
92         CM_LOG_D("maximum number of sessions reached: delete oldest session.");
93         if (DeleteFirstAbortableSession() != CM_SUCCESS) {
94             pthread_mutex_unlock(&g_lock);
95             CM_LOG_E("not found abortable session");
96             return CMR_ERROR_SESSION_REACHED_LIMIT;
97         }
98     }
99 
100     CmAddNodeAtListTail(&g_sessionList, &sessionNode->listHead);
101     ++g_sessionCount;
102     CM_LOG_D("add session count:%u", g_sessionCount);
103     pthread_mutex_unlock(&g_lock);
104 
105     return HKS_SUCCESS;
106 }
107 
ConstructSessionInfo(const struct CmSessionNodeInfo * info,struct CmSessionNode * node)108 static int32_t ConstructSessionInfo(const struct CmSessionNodeInfo *info, struct CmSessionNode *node)
109 {
110     uint32_t size = info->uri.size;
111     uint8_t *data = (uint8_t *)CMMalloc(size);
112     if (data == NULL) {
113         CM_LOG_E("malloc uri data failed");
114         return CMR_ERROR_MALLOC_FAIL;
115     }
116     (void)memcpy_s(data, size, info->uri.data, size);
117 
118     node->info.userId = info->userId;
119     node->info.uid = info->uid;
120     node->info.uri.data = data;
121     node->info.uri.size = size;
122     return CM_SUCCESS;
123 }
124 
ConstructHandle(const struct CmBlob * handle,struct CmSessionNode * node)125 static int32_t ConstructHandle(const struct CmBlob *handle, struct CmSessionNode *node)
126 {
127     uint32_t size = handle->size;
128     uint8_t *data = (uint8_t *)CMMalloc(size);
129     if (data == NULL) {
130         CM_LOG_E("malloc handle data failed");
131         return CMR_ERROR_MALLOC_FAIL;
132     }
133     (void)memcpy_s(data, size, handle->data, size);
134 
135     node->handle.data = data;
136     node->handle.size = size;
137     return CM_SUCCESS;
138 }
139 
CmCreateSession(const struct CmSessionNodeInfo * info,const struct CmBlob * handle,bool abortable)140 int32_t CmCreateSession(const struct CmSessionNodeInfo *info, const struct CmBlob *handle, bool abortable)
141 {
142     struct CmSessionNode *node = (struct CmSessionNode *)CMMalloc(sizeof(struct CmSessionNode));
143     if (node == NULL) {
144         CM_LOG_E("malloc session node failed");
145         return CMR_ERROR_MALLOC_FAIL;
146     }
147     (void)memset_s(node, sizeof(struct CmSessionNode), 0, sizeof(struct CmSessionNode));
148 
149     int32_t ret;
150     do {
151         ret = ConstructSessionInfo(info, node);
152         if (ret != CM_SUCCESS) {
153             CM_LOG_E("construct session info failed, ret = %d", ret);
154             break;
155         }
156 
157         ret = ConstructHandle(handle, node);
158         if (ret != CM_SUCCESS) {
159             CM_LOG_E("construct handle failed, ret = %d", ret);
160             break;
161         }
162 
163         node->abortable = abortable;
164 
165         ret = AddSessionNode(node);
166         if (ret != CM_SUCCESS) {
167             CM_LOG_E("add session node failed, ret = %d", ret);
168             break;
169         }
170     } while (0);
171     if (ret != CM_SUCCESS) {
172         FreeSessionNode(&node);
173     }
174 
175     return ret;
176 }
177 
IsSameBlob(const struct CmBlob * blob1,const struct CmBlob * blob2)178 static bool IsSameBlob(const struct CmBlob *blob1, const struct CmBlob *blob2)
179 {
180     if (blob1->size != blob2->size) {
181         return false;
182     }
183     if (memcmp(blob1->data, blob2->data, blob1->size) != 0) {
184         return false;
185     }
186     return true;
187 }
188 
IsSameCaller(const struct CmSessionNodeInfo * info,const struct CmSessionNode * node)189 static bool IsSameCaller(const struct CmSessionNodeInfo *info, const struct CmSessionNode *node)
190 {
191     return (info->uid == node->info.uid) && (info->userId == node->info.userId);
192 }
193 
CmQuerySession(const struct CmSessionNodeInfo * info,const struct CmBlob * handle)194 struct CmSessionNode *CmQuerySession(const struct CmSessionNodeInfo *info, const struct CmBlob *handle)
195 {
196     struct CmSessionNode *node = NULL;
197     pthread_mutex_lock(&g_lock);
198     CM_DLIST_ITER(node, &g_sessionList) {
199         if (IsSameBlob(handle, &(node->handle)) && IsSameCaller(info, node)) {
200             pthread_mutex_unlock(&g_lock);
201             return node;
202         }
203     }
204     pthread_mutex_unlock(&g_lock);
205 
206     return NULL;
207 }
208 
CmDeleteSession(const struct CmBlob * handle)209 void CmDeleteSession(const struct CmBlob *handle)
210 {
211     struct CmSessionNode *node = NULL;
212     pthread_mutex_lock(&g_lock);
213     CM_DLIST_ITER(node, &g_sessionList) {
214         if (IsSameBlob(handle, &(node->handle))) {
215             RemoveAndFreeSessionNode(&node);
216             --g_sessionCount;
217             CM_LOG_D("delete session count: %u", g_sessionCount);
218             pthread_mutex_unlock(&g_lock);
219             return;
220         }
221     }
222     pthread_mutex_unlock(&g_lock);
223 }
224 
IsNeedDelete(enum CmSessionDeleteType deleteType,const struct CmSessionNodeInfo * info,const struct CmSessionNode * node)225 static bool IsNeedDelete(enum CmSessionDeleteType deleteType, const struct CmSessionNodeInfo *info,
226     const struct CmSessionNode *node)
227 {
228     switch (deleteType) {
229         case DELETE_SESSION_BY_USERID:
230             return info->userId == node->info.userId;
231         case DELETE_SESSION_BY_UID:
232             return IsSameCaller(info, node);
233         case DELETE_SESSION_BY_URI:
234             return IsSameBlob(&(info->uri), &(node->info.uri));
235         case DELETE_SESSION_BY_ALL:
236             return IsSameCaller(info, node) && IsSameBlob(&(info->uri), &(node->info.uri));
237         default:
238             return false;
239     }
240 }
241 
DeleteSessionNode(enum CmSessionDeleteType deleteType,const struct CmSessionNodeInfo * info,struct CmSessionNode ** nodeSession)242 static void DeleteSessionNode(enum CmSessionDeleteType deleteType, const struct CmSessionNodeInfo *info,
243     struct CmSessionNode **nodeSession)
244 {
245     struct CmSessionNode *node = *nodeSession;
246     if (IsNeedDelete(deleteType, info, node)) {
247         DeleteHuksInitInfo(&(node->handle));
248         RemoveAndFreeSessionNode(nodeSession);
249         --g_sessionCount;
250         CM_LOG_D("delete session count = %u", g_sessionCount);
251     }
252 }
253 
CmDeleteSessionByNodeInfo(enum CmSessionDeleteType deleteType,const struct CmSessionNodeInfo * info)254 void CmDeleteSessionByNodeInfo(enum CmSessionDeleteType deleteType, const struct CmSessionNodeInfo *info)
255 {
256     struct CmSessionNode *node = NULL;
257 
258     pthread_mutex_lock(&g_lock);
259     CM_DLIST_SAFT_ITER(node, &g_sessionList) {
260         if (node != NULL) {
261             DeleteSessionNode(deleteType, info, &node);
262         }
263     }
264     pthread_mutex_unlock(&g_lock);
265 }
266 // LCOV_EXCL_STOP
267