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 "pake_v2_auth_server_task.h"
17 
18 #include "account_module.h"
19 #include "asy_token_manager.h"
20 #include "clib_error.h"
21 #include "common_defs.h"
22 #include "device_auth_defines.h"
23 #include "hc_log.h"
24 #include "hc_types.h"
25 #include "pake_v2_auth_task_common.h"
26 #include "pake_v2_protocol_common.h"
27 #include "protocol_common.h"
28 #include "account_version_util.h"
29 
30 enum {
31     TASK_STATUS_PAKE_FOLLOW_BEGIN = 0,
32     TASK_STATUS_PAKE_FOLLOW_STEP_ONE = 1,
33     TASK_STATUS_PAKE_FOLLOW_STEP_TWO = 2,
34     TASK_STATUS_PAKE_FOLLOW_END = 3,
35 };
36 
GetPakeV2AuthServerType(void)37 static AccountTaskType GetPakeV2AuthServerType(void)
38 {
39     return TASK_TYPE_PAKE_V2_AUTH_SERVER;
40 }
41 
DestroyAuthServerAuthTask(TaskBase * task)42 static void DestroyAuthServerAuthTask(TaskBase *task)
43 {
44     if (task == NULL) {
45         LOGD("NULL pointer and return");
46         return;
47     }
48     PakeV2AuthServerTask *innerTask = (PakeV2AuthServerTask *)task;
49     DestroyPakeAuthParams(&(innerTask->params));
50     HcFree(innerTask);
51 }
52 
DealAsyStepOneData(PakeV2AuthServerTask * task)53 static int32_t DealAsyStepOneData(PakeV2AuthServerTask *task)
54 {
55     int32_t res = VerifyPkSignPeer(&task->params);
56     if (res != HC_SUCCESS) {
57         LOGE("Step one: VerifyPkSignPeer failed for server.");
58         return HC_ERR_ACCOUNT_VERIFY_PK_SIGN;
59     }
60     if (GenerateEcdhSharedKey(&task->params) != HC_SUCCESS) {
61         LOGE("Step one: Generate ecdh shared key failed for server.");
62         return HC_ERR_ACCOUNT_ECDH_FAIL;
63     }
64     res = ServerResponsePakeV2Protocol(&task->params.pakeParams);
65     if (res != HC_SUCCESS) {
66         LOGE("Step one: ServerResponsePakeV2Protocol failed.");
67         return res;
68     }
69     if (ExtractPakeSelfId(&task->params) != HC_SUCCESS) {
70         LOGE("ConstructPayLoad peer failed.");
71         return HC_ERR_AUTH_INTERNAL;
72     }
73     return HC_SUCCESS;
74 }
75 
PrepareAsyServerStepOneData(const PakeV2AuthServerTask * innerTask,CJson * out)76 static int32_t PrepareAsyServerStepOneData(const PakeV2AuthServerTask *innerTask, CJson *out)
77 {
78     CJson *sendToPeer = CreateJson();
79     if (sendToPeer == NULL) {
80         LOGE("Create json NULL.");
81         return HC_ERR_JSON_CREATE;
82     }
83     CJson *data = CreateJson();
84     if (data == NULL) {
85         LOGE("Create json NULL.");
86         FreeJson(sendToPeer);
87         return HC_ERR_JSON_CREATE;
88     }
89     int32_t ret = HC_SUCCESS;
90     GOTO_ERR_AND_SET_RET(AddStringToJson(sendToPeer, FIELD_USER_ID,
91         (const char *)innerTask->params.userIdSelf), ret);
92     GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_STEP, RET_PAKE_AUTH_FOLLOWER_ONE), ret);
93     GOTO_ERR_AND_SET_RET(AddStringToJson(sendToPeer, FIELD_DEVICE_ID,
94         (const char *)innerTask->params.deviceIdSelf.val), ret);
95     GOTO_ERR_AND_SET_RET(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, innerTask->params.authForm), ret);
96     GOTO_ERR_AND_SET_RET(AddStringToJson(sendToPeer, FIELD_DEV_ID, (const char *)innerTask->params.devIdSelf.val), ret);
97 
98     GOTO_ERR_AND_SET_RET(AddIntToJson(data, FIELD_AUTH_KEY_ALG_ENCODE, innerTask->params.authKeyAlgEncode), ret);
99     GOTO_ERR_AND_SET_RET(AddStringToJson(data, FIELD_AUTH_PK_INFO,
100         (const char *)innerTask->params.pkInfoSelf.val), ret);
101     GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_AUTH_PK_INFO_SIGN, innerTask->params.pkInfoSignSelf.val,
102         innerTask->params.pkInfoSignSelf.length), ret);
103     GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_EPK, innerTask->params.pakeParams.epkSelf.val,
104         innerTask->params.pakeParams.epkSelf.length), ret);
105     GOTO_ERR_AND_SET_RET(AddByteToJson(data, FIELD_SALT, innerTask->params.pakeParams.salt.val,
106         innerTask->params.pakeParams.salt.length), ret);
107     GOTO_ERR_AND_SET_RET(AddObjToJson(sendToPeer, FIELD_DATA, data), ret);
108     GOTO_ERR_AND_SET_RET(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer), ret);
109 ERR:
110     FreeJson(sendToPeer);
111     FreeJson(data);
112     return ret;
113 }
114 
AsyAuthServerStepOne(TaskBase * task,const CJson * in,CJson * out,int32_t * status)115 static int32_t AsyAuthServerStepOne(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
116 {
117     PakeV2AuthServerTask *innerTask = (PakeV2AuthServerTask *)task;
118     if (innerTask->taskBase.taskStatus != TASK_STATUS_PAKE_FOLLOW_STEP_ONE) {
119         LOGE("Server step one task status error.");
120         return HC_ERR_AUTH_STATUS;
121     }
122     GOTO_IF_ERR(GetIntFromJson(in, FIELD_AUTH_FORM, &innerTask->params.authForm));
123     const char *userIdPeer = GetStringFromJson(in, FIELD_USER_ID);
124     uint32_t userIdPeerLen = HcStrlen(userIdPeer) + 1;
125     if (userIdPeer == NULL || userIdPeerLen > DEV_AUTH_USER_ID_SIZE) {
126         LOGE("Payload not contain peer userId or userId len is invalid.");
127         return HC_ERR_BAD_MESSAGE;
128     }
129     GOTO_IF_ERR(strcpy_s((char *)innerTask->params.userIdPeer, userIdPeerLen, userIdPeer));
130     GOTO_IF_ERR(ExtractPeerDeviceId(&innerTask->params, in));
131     GOTO_IF_ERR(ExtractPeerDevId(&innerTask->params, in));
132 
133     GOTO_IF_ERR(GetIntFromJson(in, FIELD_CREDENTIAL_TYPE, &innerTask->params.credentialType));
134     GOTO_IF_ERR(GetIntFromJson(in, FIELD_AUTH_KEY_ALG_ENCODE, &innerTask->params.authKeyAlgEncode));
135     GOTO_IF_ERR(GetPkInfoPeer(&innerTask->params, in));
136     GOTO_IF_ERR(GetByteFromJson(in, FIELD_AUTH_PK_INFO_SIGN, innerTask->params.pkInfoSignPeer.val,
137         innerTask->params.pkInfoSignPeer.length));
138     const char *pkInfoSignPeerStr = GetStringFromJson(in, FIELD_AUTH_PK_INFO_SIGN);
139     if (pkInfoSignPeerStr == NULL) {
140         LOGE("pkInfoSignPeer in server is null.");
141         return HC_ERR_NULL_PTR;
142     }
143     innerTask->params.pkInfoSignPeer.length = HcStrlen(pkInfoSignPeerStr) / BYTE_TO_HEX_OPER_LENGTH;
144     GOTO_IF_ERR(DealAsyStepOneData(innerTask));
145     GOTO_IF_ERR(PrepareAsyServerStepOneData(innerTask, out));
146 
147     innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_FOLLOW_STEP_TWO;
148     *status = CONTINUE;
149     return HC_SUCCESS;
150 ERR:
151     LOGE("Server step one failed.");
152     return HC_ERR_AUTH_INTERNAL;
153 }
154 
DealAsyStepTwoData(PakeV2AuthServerTask * task)155 static int32_t DealAsyStepTwoData(PakeV2AuthServerTask *task)
156 {
157     if (ServerConfirmPakeV2Protocol(&task->params.pakeParams) != HC_SUCCESS) {
158         LOGE("Server ConfirmPakeV2Protocol failed.");
159         return HC_ERR_SERVER_CONFIRM_PROTOCOL;
160     }
161     return HC_SUCCESS;
162 }
163 
SendFinalToOut(PakeV2AuthServerTask * task,CJson * out)164 static int32_t SendFinalToOut(PakeV2AuthServerTask *task, CJson *out)
165 {
166     CJson *sendToSelf = CreateJson();
167     if (sendToSelf == NULL) {
168         LOGE("Create json sendToSelf failed.");
169         return HC_ERR_JSON_CREATE;
170     }
171     CJson *sendToPeer = CreateJson();
172     if (sendToPeer == NULL) {
173         LOGE("Create json sendToPeer failed.");
174         FreeJson(sendToSelf);
175         return HC_ERR_JSON_CREATE;
176     }
177     CJson *sendToPeerData = CreateJson();
178     if (sendToPeerData == NULL) {
179         LOGE("Create json sendToPeerData failed.");
180         FreeJson(sendToPeer);
181         FreeJson(sendToSelf);
182         return HC_ERR_JSON_CREATE;
183     }
184     GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_USER_ID, (const char *)task->params.userIdPeer));
185     GOTO_IF_ERR(AddByteToJson(sendToSelf, FIELD_SESSION_KEY,
186         task->params.pakeParams.sessionKey.val, task->params.pakeParams.sessionKey.length));
187     GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_DEVICE_ID, (const char *)task->params.deviceIdSelf.val));
188     GOTO_IF_ERR(AddStringToJson(sendToSelf, FIELD_DEV_ID, (const char *)task->params.devIdPeer.val));
189     GOTO_IF_ERR(AddIntToJson(sendToSelf, FIELD_CREDENTIAL_TYPE, ASYMMETRIC_CRED));
190 
191     GOTO_IF_ERR(AddIntToJson(sendToPeer, FIELD_AUTH_FORM, task->params.authForm));
192     GOTO_IF_ERR(AddIntToJson(sendToPeer, FIELD_STEP, RET_PAKE_AUTH_FOLLOWER_TWO));
193 
194     GOTO_IF_ERR(AddByteToJson(sendToPeerData,
195         FIELD_KCF_DATA, task->params.pakeParams.kcfData.val, task->params.pakeParams.kcfData.length));
196     GOTO_IF_ERR(AddObjToJson(out, FIELD_SEND_TO_SELF, sendToSelf));
197     GOTO_IF_ERR(AddObjToJson(sendToPeer, FIELD_DATA, sendToPeerData));
198     GOTO_IF_ERR(AddObjToJson(out, FIELD_SEND_TO_PEER, sendToPeer));
199     FreeJson(sendToPeer);
200     FreeJson(sendToSelf);
201     FreeJson(sendToPeerData);
202     FreeAndCleanKey(&task->params.pakeParams.sessionKey);
203     return HC_SUCCESS;
204 ERR:
205     LOGE("Server send final failed");
206     FreeJson(sendToPeer);
207     FreeJson(sendToSelf);
208     FreeJson(sendToPeerData);
209     FreeAndCleanKey(&task->params.pakeParams.sessionKey);
210     return HC_ERR_AUTH_INTERNAL;
211 }
212 
AsyAuthServerStepTwo(TaskBase * task,const CJson * in,CJson * out,int32_t * status)213 static int32_t AsyAuthServerStepTwo(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
214 {
215     PakeV2AuthServerTask *innerTask = (PakeV2AuthServerTask *)task;
216     if (innerTask->taskBase.taskStatus != TASK_STATUS_PAKE_FOLLOW_STEP_TWO) {
217         LOGE("Server task status error");
218         return HC_ERR_AUTH_STATUS;
219     }
220     GOTO_IF_ERR(GetByteFromJson(in,
221         FIELD_EPK, innerTask->params.pakeParams.epkPeer.val, innerTask->params.pakeParams.epkPeer.length));
222     GOTO_IF_ERR(GetByteFromJson(in,
223         FIELD_KCF_DATA, innerTask->params.pakeParams.kcfDataPeer.val, innerTask->params.pakeParams.kcfDataPeer.length));
224     GOTO_IF_ERR(ExtractPakePeerId(&innerTask->params, in));
225     GOTO_IF_ERR(DealAsyStepTwoData(innerTask));
226     GOTO_IF_ERR(SendFinalToOut(innerTask, out));
227     innerTask->taskBase.taskStatus = TASK_STATUS_PAKE_FOLLOW_END;
228     *status = FINISH;
229     return HC_SUCCESS;
230 ERR:
231     LOGE("server AsyAuthServerStepTwo failed");
232     return HC_ERR_AUTH_INTERNAL;
233 }
234 
ProcessServerTask(TaskBase * task,const CJson * in,CJson * out,int32_t * status)235 static int32_t ProcessServerTask(TaskBase *task, const CJson *in, CJson *out, int32_t *status)
236 {
237     if ((task == NULL) || (in == NULL) || (out == NULL) || (status == NULL)) {
238         LOGE("invalid param");
239         return HC_ERR_INVALID_PARAMS;
240     }
241     int32_t step = 0;
242     if (GetIntFromJson(in, FIELD_STEP, &step) != HC_SUCCESS) {
243         LOGE("server no auth step");
244         return HC_ERR_JSON_GET;
245     }
246     LOGI("ProcessServerTask step: %d", step);
247     int32_t res;
248     switch (step) {
249         case CMD_PAKE_AUTH_MAIN_ONE:
250             res = AsyAuthServerStepOne(task, in, out, status);
251             break;
252         case CMD_PAKE_AUTH_MAIN_TWO:
253             res = AsyAuthServerStepTwo(task, in, out, status);
254             break;
255         case ERR_MSG:
256             return HC_ERR_PEER_ERROR;
257         default:
258             res = HC_ERR_BAD_MESSAGE;
259             break;
260     }
261     if (res != HC_SUCCESS) {
262         LOGE("Server ProcessServerTask failed, step: %d.", step);
263     }
264     return res;
265 }
266 
CreatePakeV2AuthServerTask(const CJson * in,CJson * out,const AccountVersionInfo * verInfo)267 TaskBase *CreatePakeV2AuthServerTask(const CJson *in, CJson *out, const AccountVersionInfo *verInfo)
268 {
269     if (in == NULL || out == NULL || verInfo == NULL) {
270         LOGE("Params is null.");
271         return NULL;
272     }
273     PakeV2AuthServerTask *taskParams = (PakeV2AuthServerTask *)HcMalloc(sizeof(PakeV2AuthServerTask), 0);
274     if (taskParams == NULL) {
275         LOGE("Malloc taskParams failed");
276         return NULL;
277     }
278     (void)memset_s(taskParams, sizeof(PakeV2AuthServerTask), 0, sizeof(PakeV2AuthServerTask));
279     taskParams->taskBase.getTaskType = GetPakeV2AuthServerType;
280     taskParams->taskBase.process = ProcessServerTask;
281     taskParams->taskBase.destroyTask = DestroyAuthServerAuthTask;
282 
283     if (InitPakeAuthParams(in, &(taskParams->params), verInfo) != HC_SUCCESS) {
284         LOGE("InitPakeAuthParams error.");
285         DestroyAuthServerAuthTask((TaskBase *)taskParams);
286         return NULL;
287     }
288 
289     taskParams->taskBase.taskStatus = TASK_STATUS_PAKE_FOLLOW_STEP_ONE;
290     return (TaskBase *)taskParams;
291 }