1 /*
2 * Copyright (c) 2020 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_client.h"
17 #include "log.h"
18 #include "mem_stat.h"
19
20 #if !(defined(_CUT_PAKE_) || defined(_CUT_PAKE_CLIENT_))
21
22 #include <string.h>
23 #include "securec.h"
24 #include "huks_adapter.h"
25 #include "commonutil.h"
26
27 static int32_t build_start_request_data(void *handle, void *data);
28 static int32_t parse_start_response_data(void *handle, void *data);
29 static int32_t build_end_request_data(void *handle, void *data);
30 static int32_t parse_end_response_data(void *handle, void *data);
31
32 #define HICHAIN_SPEKE_BASE_INFO "hichain_speke_base_info"
33 #define HICHAIN_RETURN_KEY "hichain_return_key"
34 #define HICHAIN_SPEKE_SESSIONKEY_INFO "hichain_speke_sessionkey_info"
35
build_pake_client(const struct session_identity * identity,const struct hc_pin * pin,uint32_t key_length,const struct hc_auth_id * client,const struct hc_auth_id * server)36 struct pake_client *build_pake_client(const struct session_identity *identity, const struct hc_pin *pin,
37 uint32_t key_length, const struct hc_auth_id *client, const struct hc_auth_id *server)
38 {
39 struct pake_client *pake_client = (struct pake_client *)MALLOC(sizeof(struct pake_client));
40 if (pake_client == NULL) {
41 LOGE("Build pake client object failed");
42 return NULL;
43 }
44
45 (void)memset_s(pake_client, sizeof(*pake_client), 0, sizeof(*pake_client));
46 struct client_virtual_func_group funcs = { build_start_request_data, parse_start_response_data,
47 build_end_request_data, parse_end_response_data };
48
49 init_client(&pake_client->client_info, &funcs);
50 pake_client->pin = *pin;
51 pake_client->key_length = key_length;
52 pake_client->self_id = *client;
53 pake_client->peer_id = *server;
54 pake_client->identity = identity;
55 pake_client->prime_type = NUM_LEN_384;
56 LOGI("Build pake client object %u success", pake_client_sn(pake_client));
57
58 return pake_client;
59 }
60
destroy_pake_client(struct pake_client * pake_client)61 void destroy_pake_client(struct pake_client *pake_client)
62 {
63 if (pake_client == NULL) {
64 return;
65 }
66
67 LOGI("Destroy pake client object %u success", pake_client_sn(pake_client));
68 (void)memset_s(&pake_client->pin, sizeof(struct hc_pin), 0, sizeof(struct hc_pin));
69 (void)memset_s(&pake_client->self_esk, sizeof(struct esk), 0, sizeof(struct esk));
70 (void)memset_s(&pake_client->session_key, sizeof(struct pake_session_key), 0, sizeof(struct pake_session_key));
71 (void)memset_s(&pake_client->hmac_key, sizeof(struct pake_hmac_key), 0, sizeof(struct pake_hmac_key));
72 (void)memset_s(&pake_client->service_key, sizeof(struct hc_session_key), 0, sizeof(struct hc_session_key));
73 FREE(pake_client);
74 }
75
send_pake_start_request(struct pake_client * pake_client,struct message * send)76 int32_t send_pake_start_request(struct pake_client *pake_client, struct message *send)
77 {
78 check_ptr_return_val(pake_client, HC_INPUT_ERROR);
79 check_ptr_return_val(send, HC_INPUT_ERROR);
80 struct pake_start_request_data *send_data =
81 (struct pake_start_request_data *)MALLOC(sizeof(struct pake_start_request_data));
82 if (send_data == NULL) {
83 LOGE("Malloc struct PAKE_START_REQUEST_DATA failed");
84 return HC_MALLOC_FAILED;
85 }
86 (void)memset_s(send_data, sizeof(*send_data), 0, sizeof(*send_data));
87
88 int32_t ret = send_start_request(pake_client, send_data);
89 if (ret != HC_OK) {
90 LOGE("Called send_start_request failed, error code is %d", ret);
91 FREE(send_data);
92 send->msg_code = INFORM_MESSAGE;
93 } else {
94 DBG_OUT("Called send_start_request success");
95 send->msg_code = PAKE_REQUEST;
96 send->payload = send_data;
97 }
98
99 return ret;
100 }
101
send_pake_end_request(struct pake_client * pake_client,const struct message * receive,struct message * send)102 int32_t send_pake_end_request(struct pake_client *pake_client, const struct message *receive, struct message *send)
103 {
104 check_ptr_return_val(pake_client, HC_INPUT_ERROR);
105 check_ptr_return_val(receive, HC_INPUT_ERROR);
106 check_ptr_return_val(send, HC_INPUT_ERROR);
107 DBG_OUT("Receive pake start response message object %u success", pake_client_sn(pake_client));
108 struct pake_start_response_data *receive_data = (struct pake_start_response_data *)receive->payload;
109
110 struct pake_end_request_data *send_data =
111 (struct pake_end_request_data *)MALLOC(sizeof(struct pake_end_request_data));
112 if (send_data == NULL) {
113 LOGE("Malloc struct pake_end_request_data failed");
114 return HC_MALLOC_FAILED;
115 }
116 (void)memset_s(send_data, sizeof(*send_data), 0, sizeof(*send_data));
117
118 int32_t ret = send_end_request(pake_client, receive_data, send_data);
119 if (ret != HC_OK) {
120 LOGE("Called send_end_request failed, error code is %d", ret);
121 FREE(send_data);
122 send->msg_code = INFORM_MESSAGE;
123 } else {
124 DBG_OUT("Called send_end_request success");
125 send->msg_code = PAKE_CLIENT_CONFIRM;
126 send->payload = send_data;
127 }
128
129 return ret;
130 }
131
receive_pake_end_response(struct pake_client * pake_client,struct message * receive)132 int32_t receive_pake_end_response(struct pake_client *pake_client, struct message *receive)
133 {
134 check_ptr_return_val(pake_client, HC_INPUT_ERROR);
135 check_ptr_return_val(receive, HC_INPUT_ERROR);
136 DBG_OUT("Receive pake end response message object %u success", pake_client_sn(pake_client));
137 struct pake_end_response_data *receive_data = (struct pake_end_response_data *)receive->payload;
138 int32_t ret = receive_end_response(pake_client, receive_data);
139 if (ret != HC_OK) {
140 LOGE("Called receive_end_response failed, error code is %d", ret);
141 receive->msg_code = INFORM_MESSAGE;
142 } else {
143 DBG_OUT("Called receive_end_response success");
144 receive->msg_code = PAKE_SERVER_CONFIRM_RESPONSE;
145 receive->payload = receive_data;
146 }
147
148 return ret;
149 }
150
build_start_request_data(void * handle,void * data)151 static int32_t build_start_request_data(void *handle, void *data)
152 {
153 struct pake_client *pake_client = (struct pake_client *)handle;
154 struct pake_start_request_data *send_data = (struct pake_start_request_data *)data;
155
156 send_data->peer_version.first = 1;
157 send_data->peer_version.second = 0;
158 send_data->peer_version.third = 0;
159 send_data->peer_support_version.first = 1;
160 send_data->peer_support_version.second = 0;
161 send_data->peer_support_version.third = 0;
162 send_data->operation_code = pake_client->operation_code;
163 send_data->epk_len = HC_BIG_PRIME_MAX_LEN;
164
165 return HC_OK;
166 }
167
gen_esk_prime_len(struct pake_client * pake_client,struct pake_start_response_data * receive,uint32_t * esk_len,uint32_t * prime_len)168 static int32_t gen_esk_prime_len(struct pake_client *pake_client, struct pake_start_response_data *receive,
169 uint32_t *esk_len, uint32_t *prime_len)
170 {
171 if (receive->epk.length == HC_BIG_PRIME_MAX_LEN_384) {
172 pake_client->prime_type = NUM_LEN_384;
173 } else if (receive->epk.length == HC_BIG_PRIME_MAX_LEN_256) {
174 pake_client->prime_type = NUM_LEN_256;
175 } else {
176 LOGE("Object %u peer is not support big number len %u", pake_client_sn(pake_client), receive->epk.length);
177 return HC_LARGE_PRIME_NUMBER_LEN_UNSUPPORT;
178 }
179 *esk_len = (pake_client->prime_type == NUM_LEN_384) ? PAKE_ESK_LENGTH : PAKE_ESK_SHORT_LENGTH;
180 *prime_len = (pake_client->prime_type == NUM_LEN_384) ?
181 HC_BIG_PRIME_MAX_LEN_384 : HC_BIG_PRIME_MAX_LEN_256;
182 return HC_OK;
183 }
184
parse_start_response_data(void * handle,void * data)185 static int32_t parse_start_response_data(void *handle, void *data)
186 {
187 struct pake_client *pake_client = (struct pake_client *)handle;
188 struct pake_start_response_data *receive = (struct pake_start_response_data *)data;
189
190 if (!is_peer_support_current_version(&receive->self_version, &receive->self_support_version)) {
191 LOGE("Unsupport version received");
192 return HC_VERSION_UNSUPPORT;
193 }
194
195 pake_client->salt = receive->salt;
196 pake_client->peer_epk = receive->epk;
197 pake_client->peer_challenge = receive->challenge;
198
199 struct hkdf secret = { 0, {0} };
200 int32_t ret = compute_hkdf((struct var_buffer *)&pake_client->pin, &pake_client->salt,
201 HICHAIN_SPEKE_BASE_INFO, HC_HKDF_SECRET_LEN, (struct var_buffer *)&secret);
202 if (ret != HC_OK) {
203 LOGE("Object %u generate hkdf failed, error code is %d", pake_client_sn(pake_client), ret);
204 return ret;
205 }
206
207 uint32_t esk_len = 0;
208 uint32_t prime_len = 0;
209 ret = gen_esk_prime_len(pake_client, receive, &esk_len, &prime_len);
210 if (ret != HC_OK) {
211 (void)memset_s(&secret, sizeof(struct hkdf), 0, sizeof(struct hkdf));
212 return ret;
213 }
214 if (pake_client->client_info.protocol_base_info.state == START_REQUEST) {
215 struct random_value rand = generate_random(esk_len);
216 if (rand.length == 0) {
217 LOGE("Generate random value failed");
218 (void)memset_s(&secret, sizeof(struct hkdf), 0, sizeof(struct hkdf));
219 return HC_GEN_RANDOM_FAILED;
220 }
221
222 pake_client->self_esk = *(struct esk *)&rand;
223 }
224 struct exponent exp = {.length = 1};
225
226 exp.exp[0] = 2; /* square */
227 struct epk base = { 0, {0} };
228
229 ret = cal_bignum_exp((struct var_buffer *)&secret, (struct var_buffer *)&exp, prime_len, (struct big_num *)&base);
230 (void)memset_s(&secret, sizeof(struct hkdf), 0, sizeof(struct hkdf));
231 if (ret != HC_OK) {
232 return HC_CAL_BIGNUM_EXP_FAILED;
233 }
234 struct epk self_epk = { 0, {0} };
235
236 ret = cal_bignum_exp((struct var_buffer *)&base, (struct var_buffer *)&pake_client->self_esk,
237 prime_len, (struct big_num *)&self_epk);
238 if (ret != HC_OK) {
239 return HC_CAL_BIGNUM_EXP_FAILED;
240 }
241 pake_client->self_epk = self_epk;
242
243 return HC_OK;
244 }
245
246 static int32_t generate_session_key(struct pake_client *pake_client, struct epk *peer_epk);
247 static struct hmac generate_proof(struct pake_client *pake_client);
build_end_request_data(void * handle,void * data)248 static int32_t build_end_request_data(void *handle, void *data)
249 {
250 struct pake_client *pake_client = (struct pake_client *)handle;
251 struct pake_end_request_data *send = (struct pake_end_request_data *)data;
252 int32_t ret = generate_session_key(pake_client, &pake_client->peer_epk);
253 if (ret != HC_OK) {
254 LOGE("Object %u generate session key failed", pake_client_sn(pake_client));
255 return ret;
256 }
257 struct challenge challenge = { 0, {0} };
258 struct random_value rand = generate_random(CHALLENGE_BUFF_LENGTH);
259 if (rand.length == CHALLENGE_BUFF_LENGTH) {
260 DBG_OUT("Generate challenge success");
261 challenge.length = rand.length;
262 if (memcpy_s(challenge.challenge, sizeof(challenge.challenge), rand.random_value,
263 CHALLENGE_BUFF_LENGTH) != EOK) {
264 return memory_copy_error(__func__, __LINE__);
265 }
266 } else {
267 LOGE("Generate challenge failed.");
268 }
269 pake_client->self_challenge = challenge;
270 pake_client->kcf_data = generate_proof(pake_client);
271 send->challenge = challenge;
272 send->epk = pake_client->self_epk;
273 send->kcf_data = pake_client->kcf_data;
274
275 return HC_OK;
276 }
277
278 static bool verify_proof_is_ok(struct pake_client *pake_client, struct hmac *kcf_data);
279 static void generate_output_key(struct pake_client *pake_client);
parse_end_response_data(void * handle,void * data)280 static int32_t parse_end_response_data(void *handle, void *data)
281 {
282 struct pake_client *pake_client = (struct pake_client *)handle;
283 struct pake_end_response_data *receive = (struct pake_end_response_data *)data;
284
285 if (verify_proof_is_ok(pake_client, &receive->kcf_data) != true) {
286 LOGE("Object %u verify proof failed", pake_client_sn(pake_client));
287 return HC_VERIFY_PROOF_FAILED;
288 }
289
290 generate_output_key(pake_client);
291
292 return HC_OK;
293 }
294
generate_session_key(struct pake_client * pake_client,struct epk * peer_epk)295 static int32_t generate_session_key(struct pake_client *pake_client, struct epk *peer_epk)
296 {
297 struct pake_shared_secret shared_secret = { 0, {0} };
298 uint32_t prime_len = (pake_client->prime_type == NUM_LEN_384) ?
299 HC_BIG_PRIME_MAX_LEN_384 : HC_BIG_PRIME_MAX_LEN_256;
300 if (CheckDlSpekePublicKey((const struct var_buffer *)peer_epk, prime_len) != HC_OK) {
301 LOGE("CheckDlSpekePublicKey failed.");
302 return HC_GENERATE_SESSION_KEY_FAILED;
303 }
304 int32_t ret = cal_bignum_exp((struct var_buffer *)peer_epk, (struct var_buffer *)&pake_client->self_esk,
305 prime_len, (struct big_num *)&shared_secret);
306 pake_client->shared_secret = shared_secret;
307 if (ret != HC_OK) {
308 LOGE("Object %u generate shared secret failed, error code is %d", pake_client_sn(pake_client), ret);
309 goto error;
310 }
311
312 struct hkdf hkdf = { 0, {0} };
313 ret = compute_hkdf((struct var_buffer *)&shared_secret, &pake_client->salt,
314 HICHAIN_SPEKE_SESSIONKEY_INFO, HC_HKDF_SECRET_LEN, (struct var_buffer *)&hkdf);
315 (void)memset_s(&shared_secret, sizeof(struct pake_shared_secret), 0, sizeof(struct pake_shared_secret));
316 if (ret != HC_OK) {
317 LOGE("Object %u generate hkdf failed, error code is %d", pake_client_sn(pake_client), ret);
318 goto error;
319 }
320
321 (void)memcpy_s(pake_client->session_key.key, sizeof(pake_client->session_key.key),
322 hkdf.hkdf, PAKE_SESSION_KEY_LENGTH);
323 (void)memcpy_s(pake_client->hmac_key.key, sizeof(pake_client->hmac_key.key),
324 hkdf.hkdf + PAKE_SESSION_KEY_LENGTH, PAKE_HMAC_KEY_LENGTH);
325 pake_client->session_key.length = PAKE_SESSION_KEY_LENGTH;
326 pake_client->hmac_key.length = PAKE_HMAC_KEY_LENGTH;
327 (void)memset_s(&hkdf, sizeof(struct hkdf), 0, sizeof(struct hkdf));
328 return HC_OK;
329
330 error:
331 pake_client->session_key.length = 0;
332 pake_client->hmac_key.length = 0;
333 return HC_GENERATE_SESSION_KEY_FAILED;
334 }
335
generate_proof(struct pake_client * pake_client)336 static struct hmac generate_proof(struct pake_client *pake_client)
337 {
338 struct hmac proof = { 0, {0} };
339 struct uint8_buff challenge = {
340 .val = NULL,
341 .length = 0,
342 .size = CHALLENGE_BUFF_LENGTH + CHALLENGE_BUFF_LENGTH
343 };
344
345 challenge.val = (uint8_t *)MALLOC(challenge.size);
346 if (challenge.val == NULL) {
347 LOGE("Object %u MALLOC generate proof buffer failed.", pake_client_sn(pake_client));
348 return proof;
349 }
350 (void)memset_s(challenge.val, challenge.size, 0, challenge.size);
351 (void)memcpy_s(challenge.val, challenge.size, pake_client->self_challenge.challenge, CHALLENGE_BUFF_LENGTH);
352 challenge.length = CHALLENGE_BUFF_LENGTH;
353 (void)memcpy_s(challenge.val + challenge.length, challenge.size - challenge.length,
354 pake_client->peer_challenge.challenge, CHALLENGE_BUFF_LENGTH);
355 challenge.length += CHALLENGE_BUFF_LENGTH;
356
357 int32_t ret = compute_hmac((struct var_buffer *)&pake_client->hmac_key, &challenge, &proof);
358 FREE(challenge.val);
359 if (ret != HC_OK) {
360 LOGE("Object %u generate proof hmac failed, error code is %d.", pake_client_sn(pake_client), ret);
361 proof.length = 0;
362 }
363 DBG_OUT("Object %u generate proof success", pake_client_sn(pake_client));
364 return proof;
365 }
366
verify_proof_is_ok(struct pake_client * pake_client,struct hmac * kcf_data)367 static bool verify_proof_is_ok(struct pake_client *pake_client, struct hmac *kcf_data)
368 {
369 struct uint8_buff challenge = {.size = CHALLENGE_BUFF_LENGTH + CHALLENGE_BUFF_LENGTH};
370
371 challenge.val = (uint8_t *)MALLOC(challenge.size);
372 if (challenge.val == NULL) {
373 LOGE("Object %u MALLOC verify proof buffer failed", pake_client_sn(pake_client));
374 return false;
375 }
376
377 (void)memcpy_s(challenge.val, challenge.size, pake_client->peer_challenge.challenge, CHALLENGE_BUFF_LENGTH);
378 challenge.length = CHALLENGE_BUFF_LENGTH;
379 (void)memcpy_s(challenge.val + challenge.length, challenge.size - challenge.length,
380 pake_client->self_challenge.challenge, CHALLENGE_BUFF_LENGTH);
381 challenge.length += CHALLENGE_BUFF_LENGTH;
382 struct hmac verify_proof = { 0, {0} };
383 int32_t ret = compute_hmac((struct var_buffer *)&pake_client->hmac_key, &challenge, &verify_proof);
384
385 FREE(challenge.val);
386 challenge.val = NULL;
387 if (ret != HC_OK) {
388 LOGE("Object %u verify proof hmac failed, error code is %d", pake_client_sn(pake_client), ret);
389 return false;
390 }
391
392 ret = memcmp(&verify_proof, kcf_data, sizeof(verify_proof));
393 LOGI("Object %u verify proof hmac result is %d", pake_client_sn(pake_client), ret);
394
395 return (ret == 0);
396 }
397
generate_output_key(struct pake_client * pake_client)398 static void generate_output_key(struct pake_client *pake_client)
399 {
400 DBG_OUT("pake client generate output key");
401 int32_t ret = compute_hkdf((struct var_buffer *)&pake_client->session_key, &pake_client->salt,
402 HICHAIN_RETURN_KEY, pake_client->key_length,
403 (struct var_buffer *)&pake_client->service_key);
404 if (ret != HC_OK) {
405 LOGE("Object %u generate output key failed, error code is %d", pake_client_sn(pake_client), ret);
406 return;
407 } else {
408 DBG_OUT("Pake client generate output key success");
409 return;
410 }
411 }
412
413 #else /* _CUT_XXX */
414
build_pake_client(const struct session_identity * identity,const struct hc_pin * pin,uint32_t key_length,const struct hc_auth_id * client,const struct hc_auth_id * server)415 struct pake_client *build_pake_client(const struct session_identity *identity, const struct hc_pin *pin,
416 uint32_t key_length, const struct hc_auth_id *client, const struct hc_auth_id *server)
417 {
418 LOGE("Donot support pake protocol");
419 (void)identity;
420 (void)pin;
421 (void)key_length;
422 (void)client;
423 (void)server;
424 return (struct pake_client *)MALLOC(sizeof(struct pake_client));
425 }
426
destroy_pake_client(struct pake_client * pake_client)427 void destroy_pake_client(struct pake_client *pake_client)
428 {
429 LOGE("Donot support pake protocol");
430 FREE(pake_client);
431 }
432
433 #endif /* _CUT_XXX */
434
435