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(int32_t osAccountId,KeyAgreeSession * session,KeyAgreeProtocol protocol,KeyAgreeType type)147 KeyAgreeResult KeyAgreeInitSession(int32_t osAccountId, KeyAgreeSession *session, KeyAgreeProtocol protocol,
148 KeyAgreeType type)
149 {
150 LOGI("Key agree init begin!");
151 if (session == NULL) {
152 LOGE("Invalid input params.");
153 return KEYAGREE_INIT_BAD_PARAMS;
154 }
155 SpekeSession *spekeSession = CreateSpekeSession(osAccountId);
156 if (spekeSession == NULL) {
157 LOGE("Init spekeSession fail!");
158 return KEYAGREE_INIT_CREATE_SESSION_FAIL;
159 }
160 if (spekeSession->checkAndInitProtocol(spekeSession, protocol) != HC_SUCCESS) {
161 LOGE("This protocol is not supported!");
162 DestroySpekeSession(spekeSession);
163 return KEYAGREE_INIT_NOT_SUPPORTED;
164 }
165 spekeSession->sessionId = session->sessionId;
166 spekeSession->protocol = protocol;
167 spekeSession->keyAgreeType = type;
168 if (protocol != KEYAGREE_PROTOCOL_ANY) {
169 spekeSession->versionInfo.versionStatus = VERSION_DECIDED;
170 if (spekeSession->initSpekeSession(spekeSession, protocol) != HC_SUCCESS) {
171 LOGE("Init protocol session fail!");
172 DestroySpekeSession(spekeSession);
173 return KEYAGREE_INIT_INIT_SESSION_FAIL;
174 }
175 } else {
176 if (type == KEYAGREE_TYPE_CLIENT) {
177 spekeSession->versionInfo.versionStatus = INITIAL;
178 } else {
179 spekeSession->versionInfo.versionStatus = VERSION_CONFIRM;
180 }
181 }
182 if (GetManagerInstance()->addSession(session, spekeSession) != HC_SUCCESS) {
183 LOGE("Add session fail!");
184 DestroySpekeSession(spekeSession);
185 return KEYAGREE_INIT_ADD_SESSION_FAIL;
186 }
187 LOGI("Init keyAgree session successfully!");
188 return KEYAGREE_SUCCESS;
189 }
190
KeyAgreeStartSession(KeyAgreeSession * session,const KeyAgreeBlob * sharedSecret,const KeyAgreeBlob * deviceId,const char * extras)191 KeyAgreeResult KeyAgreeStartSession(KeyAgreeSession *session, const KeyAgreeBlob *sharedSecret,
192 const KeyAgreeBlob *deviceId, const char *extras)
193 {
194 LOGI("Key agree start session begin!");
195 if ((sharedSecret == NULL) || (deviceId == NULL) || (session == NULL)) {
196 LOGE("Invalid input params.");
197 return KEYAGREE_START_BAD_PARAMS;
198 }
199 if (CheckKeyAgreeStartSessionParams(sharedSecret, deviceId, extras) != HC_SUCCESS) {
200 LOGE("Invalid input length!");
201 return KEYAGREE_START_INVAILD_LEN;
202 }
203 SpekeSession *spekeSession = GetManagerInstance()->getSession(session);
204 if (spekeSession == NULL) {
205 LOGE("GetSession fail!");
206 return KEYAGREE_START_GET_SESSION_FAIL;
207 }
208 int32_t res = InitKeyAgreeStartSessionParams(spekeSession, sharedSecret, deviceId, extras);
209 if (res != HC_SUCCESS) {
210 LOGE("Init params fail!");
211 return res;
212 }
213 LOGI("KeyAgree start successfully!");
214 return res;
215 }
216
KeyAgreeGenerateNextMessage(KeyAgreeSession * session,const KeyAgreeBlob * messageReceived,KeyAgreeBlob * messageToTransmit)217 KeyAgreeResult KeyAgreeGenerateNextMessage(KeyAgreeSession *session, const KeyAgreeBlob *messageReceived,
218 KeyAgreeBlob *messageToTransmit)
219 {
220 LOGI("Key agree generate next message begin!");
221 if ((session == NULL) || (messageToTransmit == NULL)) {
222 LOGE("Invalid session or messageToTransmit!");
223 return KEYAGREE_PROCESS_BAD_PARAMS;
224 }
225 if ((messageToTransmit->length < MIN_MESSAGE_LENGTH) || (messageToTransmit->length > MAX_MESSAGE_LENGTH)) {
226 LOGE("Invalid length of messageToTransmit!");
227 return KEYAGREE_PROCESS_INVAILD_LEN;
228 }
229 if (messageReceived != NULL && messageReceived->data != NULL &&
230 strnlen((const char *)(messageReceived->data), messageReceived->length) > messageReceived->length + 1) {
231 LOGE("Length of messageToTransmit check fail!");
232 return KEYAGREE_PROCESS_INVAILD_LEN;
233 }
234 if (messageReceived != NULL && messageReceived->data != NULL && IsErrorMessage(messageReceived)) {
235 LOGE("Peer is onError!");
236 return KEYAGREE_PROCESS_PEER_IS_ONERROR;
237 }
238 SpekeSession *spekeSession = GetManagerInstance()->getSession(session);
239 if (spekeSession == NULL) {
240 LOGE("GetSession fail!");
241 return KEYAGREE_PROCESS_GET_SESSION_FAIL;
242 }
243 if ((messageReceived == NULL) && (spekeSession->step != STEP_INIT)) {
244 LOGE("This is not first step, messageReceived is null!");
245 return KEYAGREE_PROCESS_BAD_PARAMS;
246 }
247 if (spekeSession->versionInfo.versionStatus != VERSION_DECIDED) {
248 LOGI("Protocol is not decided, need protocol agree!");
249 if (spekeSession->processProtocolAgree(spekeSession, messageReceived, messageToTransmit) != HC_SUCCESS) {
250 LOGE("Protocol agree fail!");
251 BuildErrorMessage(KEYAGREE_FAIL, messageToTransmit);
252 return KEYAGREE_PROCESS_PROTOCOL_AGREE_FAIL;
253 }
254 } else {
255 LOGI("Protocol decided, process key agree!");
256 if (spekeSession->processSession(spekeSession, messageReceived, messageToTransmit) != HC_SUCCESS) {
257 LOGE("Protocol agree fail!");
258 BuildErrorMessage(KEYAGREE_FAIL, messageToTransmit);
259 return KEYAGREE_PROCESS_PROTOCOL_SESSION_FAIL;
260 }
261 }
262 LOGI("KeyAgree generate next message successfully!");
263 return KEYAGREE_SUCCESS;
264 }
265
KeyAgreeIsFinish(KeyAgreeSession * session)266 KeyAgreeResult KeyAgreeIsFinish(KeyAgreeSession *session)
267 {
268 LOGI("Key agree is finish start!");
269 if (session == NULL) {
270 LOGE("Invalid input params.");
271 return KEYAGREE_IS_FINSIH_BAD_PARAMS;
272 }
273 KeyAgreeSessionManager *sessionManager = GetManagerInstance();
274 if (sessionManager == NULL) {
275 LOGE("Get session mgr fail!");
276 return KEYAGREE_IS_FINSIH_GET_SESSION_MGR_FAIL;
277 }
278 SpekeSession *spekeSession = sessionManager->getSession(session);
279 if (spekeSession == NULL) {
280 LOGE("GetSession fail!");
281 return KEYAGREE_IS_FINSIH_GET_SESSION_FAIL;
282 }
283 if (!spekeSession->isFinish) {
284 LOGE("Keg agree is not finish!");
285 return KEYAGREE_IS_FINSIH_NOT_FINSIH;
286 }
287 LOGI("Keg agree is finish!");
288 return KEYAGREE_SUCCESS;
289 }
290
KeyAgreeGetResult(KeyAgreeSession * session,KeyAgreeBlob * sessionKey)291 KeyAgreeResult KeyAgreeGetResult(KeyAgreeSession *session, KeyAgreeBlob *sessionKey)
292 {
293 LOGI("Key agree get result start!");
294 if ((session == NULL) || (sessionKey == NULL)) {
295 LOGE("Invalid session or sessionKey!");
296 return KEYAGREE_GET_RESULT_BAD_PARAMS;
297 }
298 if ((sessionKey->length < MIN_SESSIONKEY_LENGTH) || (sessionKey->length > MAX_SESSIONKEY_LENGTH)) {
299 LOGE("Invalid length of sessionKey!");
300 return KEYAGREE_GET_RESULT_INVAILD_LEN;
301 }
302 KeyAgreeSessionManager *sessionManager = GetManagerInstance();
303 if (sessionManager == NULL) {
304 LOGE("Get session mgr fail!");
305 return KEYAGREE_GET_RESULT_GET_SESSION_MGR_FAIL;
306 }
307 SpekeSession *spekeSession = sessionManager->getSession(session);
308 if (spekeSession == NULL) {
309 LOGE("GetSession fail!");
310 return KEYAGREE_GET_RESULT_GET_SESSION_FAIL;
311 }
312 if (!spekeSession->isFinish) {
313 LOGE("Keg agree is not finish, sessionKey is not generate!");
314 return KEYAGREE_GET_RESULT_NOT_FINSIH;
315 }
316 if (memcpy_s(sessionKey->data, spekeSession->baseParam.sessionKey.length + 1,
317 spekeSession->baseParam.sessionKey.val, spekeSession->baseParam.sessionKey.length + 1) != EOK) {
318 LOGE("Memcpy for seesionKey failed.");
319 return KEYAGREE_GET_RESULT_MEMCPY_FAILED;
320 }
321 sessionKey->length = spekeSession->baseParam.sessionKey.length;
322 LOGI("Keg agree is finish, return seesionKey.");
323 return KEYAGREE_SUCCESS;
324 }
325
KeyAgreeFreeSession(KeyAgreeSession * session)326 void KeyAgreeFreeSession(KeyAgreeSession *session)
327 {
328 LOGI("Key agree free session start!");
329 if (session == NULL) {
330 LOGE("Invalid params!");
331 return;
332 }
333 KeyAgreeSessionManager *sessionManager = GetManagerInstance();
334 if (sessionManager == NULL) {
335 LOGE("Get session mgr fail!");
336 return;
337 }
338 SpekeSession *spekeSession = sessionManager->getSession(session);
339 if (spekeSession == NULL) {
340 LOGE("GetSession fail!");
341 return;
342 }
343 if (sessionManager == NULL || sessionManager->deleteSession(session) != HC_SUCCESS) {
344 LOGE("Delete session fail!");
345 return;
346 }
347 DestroySpekeSession(spekeSession);
348 }