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 }