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 "key_agree_sdk.h"
17
18 #include "hc_log.h"
19 #include "key_agree_session.h"
20 #include "key_agree_session_manager.h"
21 #include "protocol_common.h"
22
23 #define MIN_SHARED_SECRET_LENGTH 6
24 #define MAX_SHARED_SECRET_LENGTH 64
25 #define MIN_DEVICE_ID_LENGTH 16
26 #define MAX_DEVICE_ID_LENGTH 256
27 #define MIN_MESSAGE_LENGTH 2048
28 #define MAX_MESSAGE_LENGTH 4096
29 #define MIN_SESSIONKEY_LENGTH 64
30 #define MAX_SESSIONKEY_LENGTH 1024
31 #define MAX_EXTRAS_LENGTH 4096
32
CheckKeyAgreeStartSessionParams(const KeyAgreeBlob * sharedSecret,const KeyAgreeBlob * deviceId,const char * extras)33 static int32_t CheckKeyAgreeStartSessionParams(const KeyAgreeBlob *sharedSecret,
34 const KeyAgreeBlob *deviceId, const char *extras)
35 {
36 if ((sharedSecret->length < MIN_SHARED_SECRET_LENGTH) || (sharedSecret->length > MAX_SHARED_SECRET_LENGTH)) {
37 LOGE("Invalid length of sharedSecret!");
38 return HC_ERR_INVALID_PARAMS;
39 }
40 if (strnlen((const char *)(sharedSecret->data), sharedSecret->length) > sharedSecret->length + 1) {
41 LOGE("Length of sharedSecret check fail!");
42 return HC_ERR_INVALID_PARAMS;
43 }
44 if ((deviceId->length < MIN_DEVICE_ID_LENGTH) || (deviceId->length > MAX_DEVICE_ID_LENGTH)) {
45 LOGE("Invalid length of deviceId!");
46 return HC_ERR_INVALID_PARAMS;
47 }
48 if (strnlen((const char *)(deviceId->data), deviceId->length) > deviceId->length + 1) {
49 LOGE("Length of deviceId check fail!");
50 return HC_ERR_INVALID_PARAMS;
51 }
52 if (((extras != NULL) && (HcStrlen(extras) > MAX_EXTRAS_LENGTH))) {
53 LOGE("Invalid length of extras!");
54 return HC_ERR_INVALID_PARAMS;
55 }
56 return HC_SUCCESS;
57 }
58
BuildErrorMessage(KeyAgreeResult errorCode,KeyAgreeBlob * out)59 static void BuildErrorMessage(KeyAgreeResult errorCode, KeyAgreeBlob *out)
60 {
61 CJson *outJson = CreateJson();
62 if (outJson == NULL) {
63 LOGE("Create json failed!");
64 return;
65 }
66 int32_t res = AddIntToJson(outJson, FIELD_SDK_ERROR_CODE, errorCode);
67 if (res != HC_SUCCESS) {
68 LOGE("Add errorCode failed, res: %d.", res);
69 FreeJson(outJson);
70 return;
71 }
72 char *returnStr = PackJsonToString(outJson);
73 FreeJson(outJson);
74 if (returnStr == NULL) {
75 LOGE("Pack json to string failed!");
76 return;
77 }
78 uint32_t returnStrLen = HcStrlen(returnStr);
79 if (memcpy_s(out->data, out->length, returnStr, returnStrLen + 1) != EOK) {
80 LOGE("Memcpy for out json failed.");
81 }
82 out->length = returnStrLen + 1;
83 FreeJsonString(returnStr);
84 }
85
IsErrorMessage(const KeyAgreeBlob * in)86 static bool IsErrorMessage(const KeyAgreeBlob *in)
87 {
88 int32_t errorCode;
89 CJson *inJson = CreateJsonFromString((const char *)(in->data));
90 if (inJson == NULL) {
91 LOGE("Create json failed!");
92 return true;
93 }
94 if (GetIntFromJson(inJson, FIELD_SDK_ERROR_CODE, &errorCode) != HC_SUCCESS) {
95 LOGE("There is no field named errorCode!");
96 FreeJson(inJson);
97 return true;
98 }
99 FreeJson(inJson);
100 if (errorCode != KEYAGREE_SUCCESS) {
101 LOGE("Peer is onError, errorCode: %d.!", errorCode);
102 return true;
103 }
104 return false;
105 }
106
InitKeyAgreeStartSessionParams(SpekeSession * spekeSession,const KeyAgreeBlob * sharedSecret,const KeyAgreeBlob * deviceId,const char * extras)107 static int32_t InitKeyAgreeStartSessionParams(SpekeSession *spekeSession, const KeyAgreeBlob *sharedSecret,
108 const KeyAgreeBlob *deviceId, const char *extras)
109 {
110 int32_t res = KEYAGREE_SUCCESS;
111 do {
112 if (InitSingleParam(&(spekeSession->sharedSecret), sharedSecret->length) != HC_SUCCESS) {
113 LOGE("Init sharedSecret failed!");
114 res = KEYAGREE_START_INIT_PARAMS_SHAREDSECRET_FAIL;
115 break;
116 }
117 if (memcpy_s(spekeSession->sharedSecret.val, spekeSession->sharedSecret.length,
118 sharedSecret->data, sharedSecret->length) != HC_SUCCESS) {
119 LOGE("Memcpy for sharedSecret code failed.");
120 res = KEYAGREE_START_MEMORY_COPY_SHAREDSECRET_FAIL;
121 break;
122 }
123 if (InitSingleParam(&(spekeSession->deviceId), deviceId->length) != HC_SUCCESS) {
124 LOGE("Init deviceId failed!");
125 res = KEYAGREE_START_MEMORY_COPY_DEVID_FAIL;
126 break;
127 }
128 if (memcpy_s(spekeSession->deviceId.val, spekeSession->deviceId.length,
129 deviceId->data, deviceId->length) != HC_SUCCESS) {
130 LOGE("Memcpy for deviceId failed.");
131 res = KEYAGREE_START_MEMORY_COPY_DEVID_FAIL;
132 break;
133 }
134 if (extras != NULL) {
135 LOGI("This field named extras is not used in this version!");
136 }
137 } while (0);
138 if (res != HC_SUCCESS) {
139 FreeAndCleanKey(&spekeSession->sharedSecret);
140 FreeAndCleanKey(&spekeSession->deviceId);
141 HcFree(spekeSession->extras);
142 spekeSession->extras = NULL;
143 }
144 return res;
145 }
146
KeyAgreeInitSession(KeyAgreeSession * session,KeyAgreeProtocol protocol,KeyAgreeType type)147 KeyAgreeResult KeyAgreeInitSession(KeyAgreeSession *session, KeyAgreeProtocol protocol, KeyAgreeType type)
148 {
149 LOGI("Key agree init begin!");
150 if (session == NULL) {
151 LOGE("Invalid input params.");
152 return KEYAGREE_INIT_BAD_PARAMS;
153 }
154 SpekeSession *spekeSession = CreateSpekeSession();
155 if (spekeSession == NULL) {
156 LOGE("Init spekeSession fail!");
157 return KEYAGREE_INIT_CREATE_SESSION_FAIL;
158 }
159 if (spekeSession->checkAndInitProtocol(spekeSession, protocol) != HC_SUCCESS) {
160 LOGE("This protocol is not supported!");
161 DestroySpekeSession(spekeSession);
162 return KEYAGREE_INIT_NOT_SUPPORTED;
163 }
164 spekeSession->sessionId = session->sessionId;
165 spekeSession->protocol = protocol;
166 spekeSession->keyAgreeType = type;
167 if (protocol != KEYAGREE_PROTOCOL_ANY) {
168 spekeSession->versionInfo.versionStatus = VERSION_DECIDED;
169 if (spekeSession->initSpekeSession(spekeSession, protocol) != HC_SUCCESS) {
170 LOGE("Init protocol session fail!");
171 DestroySpekeSession(spekeSession);
172 return KEYAGREE_INIT_INIT_SESSION_FAIL;
173 }
174 } else {
175 if (type == KEYAGREE_TYPE_CLIENT) {
176 spekeSession->versionInfo.versionStatus = INITIAL;
177 } else {
178 spekeSession->versionInfo.versionStatus = VERSION_CONFIRM;
179 }
180 }
181 if (GetManagerInstance()->addSession(session, spekeSession) != HC_SUCCESS) {
182 LOGE("Add session fail!");
183 DestroySpekeSession(spekeSession);
184 return KEYAGREE_INIT_ADD_SESSION_FAIL;
185 }
186 LOGI("Init keyAgree session successfully!");
187 return KEYAGREE_SUCCESS;
188 }
189
KeyAgreeStartSession(KeyAgreeSession * session,const KeyAgreeBlob * sharedSecret,const KeyAgreeBlob * deviceId,const char * extras)190 KeyAgreeResult KeyAgreeStartSession(KeyAgreeSession *session, const KeyAgreeBlob *sharedSecret,
191 const KeyAgreeBlob *deviceId, const char *extras)
192 {
193 LOGI("Key agree start session begin!");
194 if ((sharedSecret == NULL) || (deviceId == NULL) || (session == NULL)) {
195 LOGE("Invalid input params.");
196 return KEYAGREE_START_BAD_PARAMS;
197 }
198 if (CheckKeyAgreeStartSessionParams(sharedSecret, deviceId, extras) != HC_SUCCESS) {
199 LOGE("Invalid input length!");
200 return KEYAGREE_START_INVAILD_LEN;
201 }
202 SpekeSession *spekeSession = GetManagerInstance()->getSession(session);
203 if (spekeSession == NULL) {
204 LOGE("GetSession fail!");
205 return KEYAGREE_START_GET_SESSION_FAIL;
206 }
207 int32_t res = InitKeyAgreeStartSessionParams(spekeSession, sharedSecret, deviceId, extras);
208 if (res != HC_SUCCESS) {
209 LOGE("Init params fail!");
210 return res;
211 }
212 LOGI("KeyAgree start successfully!");
213 return res;
214 }
215
KeyAgreeGenerateNextMessage(KeyAgreeSession * session,const KeyAgreeBlob * messageReceived,KeyAgreeBlob * messageToTransmit)216 KeyAgreeResult KeyAgreeGenerateNextMessage(KeyAgreeSession *session, const KeyAgreeBlob *messageReceived,
217 KeyAgreeBlob *messageToTransmit)
218 {
219 LOGI("Key agree generate next message begin!");
220 if ((session == NULL) || (messageToTransmit == NULL)) {
221 LOGE("Invalid session or messageToTransmit!");
222 return KEYAGREE_PROCESS_BAD_PARAMS;
223 }
224 if ((messageToTransmit->length < MIN_MESSAGE_LENGTH) || (messageToTransmit->length > MAX_MESSAGE_LENGTH)) {
225 LOGE("Invalid length of messageToTransmit!");
226 return KEYAGREE_PROCESS_INVAILD_LEN;
227 }
228 if (messageReceived != NULL && messageReceived->data != NULL &&
229 strnlen((const char *)(messageReceived->data), messageReceived->length) > messageReceived->length + 1) {
230 LOGE("Length of messageToTransmit check fail!");
231 return KEYAGREE_PROCESS_INVAILD_LEN;
232 }
233 if (messageReceived != NULL && messageReceived->data != NULL && IsErrorMessage(messageReceived)) {
234 LOGE("Peer is onError!");
235 return KEYAGREE_PROCESS_PEER_IS_ONERROR;
236 }
237 SpekeSession *spekeSession = GetManagerInstance()->getSession(session);
238 if (spekeSession == NULL) {
239 LOGE("GetSession fail!");
240 return KEYAGREE_PROCESS_GET_SESSION_FAIL;
241 }
242 if ((messageReceived == NULL) && (spekeSession->step != STEP_INIT)) {
243 LOGE("This is not first step, messageReceived is null!");
244 return KEYAGREE_PROCESS_BAD_PARAMS;
245 }
246 if (spekeSession->versionInfo.versionStatus != VERSION_DECIDED) {
247 LOGI("Protocol is not decided, need protocol agree!");
248 if (spekeSession->processProtocolAgree(spekeSession, messageReceived, messageToTransmit) != HC_SUCCESS) {
249 LOGE("Protocol agree fail!");
250 BuildErrorMessage(KEYAGREE_FAIL, messageToTransmit);
251 return KEYAGREE_PROCESS_PROTOCOL_AGREE_FAIL;
252 }
253 } else {
254 LOGI("Protocol decided, process key agree!");
255 if (spekeSession->processSession(spekeSession, messageReceived, messageToTransmit) != HC_SUCCESS) {
256 LOGE("Protocol agree fail!");
257 BuildErrorMessage(KEYAGREE_FAIL, messageToTransmit);
258 return KEYAGREE_PROCESS_PROTOCOL_SESSION_FAIL;
259 }
260 }
261 LOGI("KeyAgree generate next message successfully!");
262 return KEYAGREE_SUCCESS;
263 }
264
KeyAgreeIsFinish(KeyAgreeSession * session)265 KeyAgreeResult KeyAgreeIsFinish(KeyAgreeSession *session)
266 {
267 LOGI("Key agree is finish start!");
268 if (session == NULL) {
269 LOGE("Invalid input params.");
270 return KEYAGREE_IS_FINSIH_BAD_PARAMS;
271 }
272 KeyAgreeSessionManager *sessionManager = GetManagerInstance();
273 if (sessionManager == NULL) {
274 LOGE("Get session mgr fail!");
275 return KEYAGREE_IS_FINSIH_GET_SESSION_MGR_FAIL;
276 }
277 SpekeSession *spekeSession = sessionManager->getSession(session);
278 if (spekeSession == NULL) {
279 LOGE("GetSession fail!");
280 return KEYAGREE_IS_FINSIH_GET_SESSION_FAIL;
281 }
282 if (!spekeSession->isFinish) {
283 LOGE("Keg agree is not finish!");
284 return KEYAGREE_IS_FINSIH_NOT_FINSIH;
285 }
286 LOGI("Keg agree is finish!");
287 return KEYAGREE_SUCCESS;
288 }
289
KeyAgreeGetResult(KeyAgreeSession * session,KeyAgreeBlob * sessionKey)290 KeyAgreeResult KeyAgreeGetResult(KeyAgreeSession *session, KeyAgreeBlob *sessionKey)
291 {
292 LOGI("Key agree get result start!");
293 if ((session == NULL) || (sessionKey == NULL)) {
294 LOGE("Invalid session or sessionKey!");
295 return KEYAGREE_GET_RESULT_BAD_PARAMS;
296 }
297 if ((sessionKey->length < MIN_SESSIONKEY_LENGTH) || (sessionKey->length > MAX_SESSIONKEY_LENGTH)) {
298 LOGE("Invalid length of sessionKey!");
299 return KEYAGREE_GET_RESULT_INVAILD_LEN;
300 }
301 KeyAgreeSessionManager *sessionManager = GetManagerInstance();
302 if (sessionManager == NULL) {
303 LOGE("Get session mgr fail!");
304 return KEYAGREE_GET_RESULT_GET_SESSION_MGR_FAIL;
305 }
306 SpekeSession *spekeSession = sessionManager->getSession(session);
307 if (spekeSession == NULL) {
308 LOGE("GetSession fail!");
309 return KEYAGREE_GET_RESULT_GET_SESSION_FAIL;
310 }
311 if (!spekeSession->isFinish) {
312 LOGE("Keg agree is not finish, sessionKey is not generate!");
313 return KEYAGREE_GET_RESULT_NOT_FINSIH;
314 }
315 if (memcpy_s(sessionKey->data, spekeSession->baseParam.sessionKey.length + 1,
316 spekeSession->baseParam.sessionKey.val, spekeSession->baseParam.sessionKey.length + 1) != EOK) {
317 LOGE("Memcpy for seesionKey failed.");
318 return KEYAGREE_GET_RESULT_MEMCPY_FAILED;
319 }
320 sessionKey->length = spekeSession->baseParam.sessionKey.length;
321 LOGI("Keg agree is finish, return seesionKey.");
322 return KEYAGREE_SUCCESS;
323 }
324
KeyAgreeFreeSession(KeyAgreeSession * session)325 void KeyAgreeFreeSession(KeyAgreeSession *session)
326 {
327 LOGI("Key agree free session start!");
328 if (session == NULL) {
329 LOGE("Invalid params!");
330 return;
331 }
332 KeyAgreeSessionManager *sessionManager = GetManagerInstance();
333 if (sessionManager == NULL) {
334 LOGE("Get session mgr fail!");
335 return;
336 }
337 SpekeSession *spekeSession = sessionManager->getSession(session);
338 if (spekeSession == NULL) {
339 LOGE("GetSession fail!");
340 return;
341 }
342 if (sessionManager == NULL || sessionManager->deleteSession(session) != HC_SUCCESS) {
343 LOGE("Delete session fail!");
344 return;
345 }
346 DestroySpekeSession(spekeSession);
347 }