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 #if !(defined(_CUT_PAKE_) || defined(_CUT_PAKE_CLIENT_) || defined(_CUT_EXCHANGE_) || defined(_CUT_EXCHANGE_CLIENT_))
17 #include "exchange_auth_info_client.h"
18 #include "securec.h"
19 #include "log.h"
20 #include "base.h"
21 #include "mem_stat.h"
22 #include "parsedata.h"
23 #include "commonutil.h"
24 #include "huks_adapter.h"
25 
26 #ifdef DESC
27 #undef DESC
28 #endif
29 #define DESC(...) 1
30 
31 #define HC_EXCHANGE_REQUEST_LEN 1024
32 
33 #define HICHAIN_EXCHANGE_REQUEST  "hichain_exchange_request"
34 #define HICHAIN_EXCHANGE_RESPONSE "hichain_exchange_response"
35 
36 static int32_t build_exchange_request(const struct hichain *hichain, exchange_request_data *send);
37 static int32_t get_field_from_request_payload(struct uint8_buff *payload, struct signature *sign_result,
38     struct hc_auth_id *auth_id, struct ltpk *ltpk);
39 static int32_t verify_peer_public_key(const struct hichain *hichain, struct uint8_buff *auth_info,
40     struct signature *sign_result, struct ltpk *ltpk);
41 static int32_t parse_exchange_response_data(const struct hichain *hichain, const exchange_request_data *receive,
42     struct auth_info_cache *cache);
43 #if DESC("interface")
send_exchange_request(const struct hichain * hichain,struct message * send)44 int32_t send_exchange_request(const struct hichain *hichain, struct message *send)
45 {
46     exchange_request_data *send_data = malloc_auth_info_msg(HC_EXCHANGE_REQUEST_LEN);
47     if (send_data == NULL) {
48         LOGE("Malloc exchange request data failed");
49         send->msg_code = INFORM_MESSAGE;
50         return HC_MALLOC_FAILED;
51     }
52 
53     int32_t ret = build_exchange_request(hichain, send_data);
54     if (ret != HC_OK) {
55         LOGE("Build exchange request failed, error code is %d", ret);
56         free_auth_info_msg(send_data);
57         send_data = NULL;
58         send->msg_code = INFORM_MESSAGE;
59         return ret;
60     }
61 
62     DBG_OUT("Send exchange request success");
63     send->payload = send_data;
64     send->msg_code = EXCHANGE_REQUEST;
65     return HC_OK;
66 }
67 
receive_exchange_response(const struct hichain * hichain,const struct message * receive)68 int32_t receive_exchange_response(const struct hichain *hichain, const struct message *receive)
69 {
70     struct auth_info_cache cache = { HC_USER_TYPE_ACCESSORY, {0, {0}}, {0, {0}}};
71 
72     int32_t ret = parse_exchange_response_data(hichain, (exchange_request_data *)receive->payload, &cache);
73     if (ret != HC_OK) {
74         LOGE("Parse exchange response data failed, error code is %d", ret);
75         return ret;
76     }
77 
78     ret = save_auth_info(hichain, HC_PAIR_TYPE_BIND, &cache);
79     if (ret != HC_OK) {
80         LOGE("Save ltpk failed, error code is %d", ret);
81         return ret;
82     }
83     return HC_OK;
84 }
85 #endif /* DESC */
86 
parse_exchange_response_data(const struct hichain * hichain,const exchange_request_data * receive,struct auth_info_cache * cache)87 static int32_t parse_exchange_response_data(const struct hichain *hichain,
88     const exchange_request_data *receive, struct auth_info_cache *cache)
89 {
90     if (hichain->pake_client == NULL) {
91         LOGE("Pake client is null");
92         return HC_PAKE_OBJECT_ERROR;
93     }
94     const struct pake_session_key *key = &hichain->pake_client->session_key;
95     if (key->length < PAKE_SESSION_KEY_LENGTH) {
96         LOGE("Get pake session key failed");
97         return HC_PAKE_SESSION_KEY_ERROR;
98     }
99     struct uint8_buff plain = { 0, 0, 0 };
100     int32_t ret = decrypt_payload((struct var_buffer *)key, &receive->cipher, HICHAIN_EXCHANGE_RESPONSE, &plain);
101     if (ret != HC_OK) {
102         LOGE("Decrypt exchange request payload failed");
103         return ret;
104     }
105 
106     struct signature sign_result;
107     ret = get_field_from_request_payload(&plain, &sign_result, &cache->auth_id, &cache->ltpk);
108     if (ret != HC_OK) {
109         LOGE("Get field from exchange response message failed, error code is %d", ret);
110         (void)memset_s(plain.val, plain.size, 0, plain.size);
111         FREE(plain.val);
112         return ret;
113     }
114     struct uint8_buff *auth_info = &plain;
115     ret = verify_peer_public_key(hichain, auth_info, &sign_result, &cache->ltpk);
116     (void)memset_s(plain.val, plain.size, 0, plain.size);
117     FREE(plain.val);
118     if (ret != HC_OK) {
119         LOGE("Verify exchange request message failed, error code is %d", ret);
120         return ret;
121     }
122 
123     return HC_OK;
124 }
125 
126 static int32_t build_auth_info(struct uint8_buff *auth_info, const struct hc_auth_id *auth_id, struct ltpk *ltpk);
127 static int32_t sign_self_public_key(const struct hichain *hichain, struct uint8_buff *auth_info,
128     const struct hc_auth_id *auth_id, struct signature *sign_result);
129 static int32_t get_self_key_id(const struct hichain *hichain, const struct hc_auth_id *auth_id, struct ltpk *ltpk);
build_exchange_request(const struct hichain * hichain,exchange_request_data * send)130 static int32_t build_exchange_request(const struct hichain *hichain, exchange_request_data *send)
131 {
132     const struct hc_auth_id *auth_id = &hichain->pake_client->self_id;
133     struct ltpk ltpk;
134     int32_t ret = get_self_key_id(hichain, auth_id, &ltpk);
135     if (ret != HC_OK) {
136         LOGE("Get ltpk failed, error code is %d", ret);
137         return ret;
138     }
139 
140     struct uint8_buff auth_info = { NULL, 0, 0 };
141     ret = build_auth_info(&auth_info, auth_id, &ltpk);
142     if (ret != HC_OK) {
143         return HC_BUILD_OBJECT_FAILED;
144     }
145     struct signature sign_result = { 0, {0} };
146     ret = sign_self_public_key(hichain, &auth_info, auth_id, &sign_result);
147     if (ret != HC_OK) {
148         FREE(auth_info.val);
149         LOGE("Sign self public key failed, error code is %d", ret);
150         return ret;
151     }
152 
153     struct uint8_buff plain;
154     plain.size = auth_info.length + sign_result.length;
155     plain.val = (uint8_t *)MALLOC(plain.size);
156     if (plain.val == NULL) {
157         FREE(auth_info.val);
158         return HC_MALLOC_FAILED;
159     }
160     (void)memset_s(plain.val, plain.size, 0, plain.size);
161     if (memcpy_s(plain.val, plain.size, auth_info.val, auth_info.length) != EOK) {
162         FREE(auth_info.val);
163         FREE(plain.val);
164         return memory_copy_error(__func__, __LINE__);
165     }
166     plain.length = auth_info.length;
167     FREE(auth_info.val);
168     if (memcpy_s(plain.val + plain.length, plain.size - plain.length, sign_result.signature, sign_result.length)
169         != EOK) {
170         FREE(plain.val);
171         return memory_copy_error(__func__, __LINE__);
172     }
173     plain.length += sign_result.length;
174 
175     const struct pake_session_key *key = &hichain->pake_client->session_key;
176     ret = encrypt_payload((struct var_buffer *)key, &plain, HICHAIN_EXCHANGE_REQUEST, &send->cipher);
177     FREE(plain.val);
178     if (ret != HC_OK) {
179         LOGE("Encrypt payload failed, error code is %d", ret);
180         return HC_ENCRYPT_FAILED;
181     }
182 
183     return HC_OK;
184 }
185 
get_self_key_id(const struct hichain * hichain,const struct hc_auth_id * auth_id,struct ltpk * ltpk)186 static int32_t get_self_key_id(const struct hichain *hichain, const struct hc_auth_id *auth_id, struct ltpk *ltpk)
187 {
188     struct service_id service_id = generate_service_id(&hichain->identity);
189     if (service_id.length == 0) {
190         LOGE("Generate service id failed");
191         return HC_GEN_SERVICE_ID_FAILED;
192     }
193 #if (defined(_SUPPORT_SEC_CLONE_) || defined(_SUPPORT_SEC_CLONE_SERVER_))
194     struct hc_key_alias alias = generate_key_alias(&service_id, auth_id, KEY_ALIAS_LT_KEY_PAIR);
195 #else
196     struct hc_key_alias alias = generate_key_alias(&service_id, auth_id, KEY_ALIAS_ACCESSOR_PK);
197 #endif
198     if (alias.length == 0) {
199         LOGE("Generate key alias failed");
200         return HC_GEN_ALIAS_FAILED;
201     }
202     int32_t ret = check_lt_public_key_exist(&alias);
203     if (ret != HC_OK) {
204         ret = generate_lt_key_pair(&alias, auth_id);
205         if (ret != HC_OK) {
206             LOGE("Generate self ltpk return value is %d", ret);
207             return HC_GET_LTPK_FAILED;
208         }
209     }
210 
211     ret = export_lt_public_key(&alias, ltpk);
212     if (ret != HC_OK) {
213         LOGE("Get self ltpk failed, error code is %d", ret);
214         return HC_GET_LTPK_FAILED;
215     }
216     DBG_OUT("Get ltpk success");
217     return HC_OK;
218 }
219 
220 static int32_t parse_auth_info(const struct uint8_buff *auth_info, struct hc_auth_id *auth_id, struct ltpk *ltpk);
get_field_from_request_payload(struct uint8_buff * payload,struct signature * sign_result,struct hc_auth_id * auth_id,struct ltpk * ltpk)221 static int32_t get_field_from_request_payload(struct uint8_buff *payload, struct signature *sign_result,
222     struct hc_auth_id *auth_id, struct ltpk *ltpk)
223 {
224     if (payload->length <= HC_SIGNATURE_LEN) {
225         LOGE("Peer public key signature info length is %d", payload->length);
226         return HC_SIGN_TOO_SHORT;
227     }
228     struct uint8_buff *auth_info = payload;
229 
230     auth_info->length -= HC_SIGNATURE_LEN;
231     (void)memcpy_s(sign_result->signature, sizeof(sign_result->signature),
232                    auth_info->val + auth_info->length, HC_SIGNATURE_LEN);
233     sign_result->length = HC_SIGNATURE_LEN;
234     auth_info->val[auth_info->length] = 0;
235     int32_t ret = parse_auth_info(auth_info, auth_id, ltpk);
236     if (ret != HC_OK) {
237         LOGE("Get auth id & ltpk failed, error code is %d", ret);
238         return ret;
239     }
240 
241     return HC_OK;
242 }
243 
244 typedef void (*COPY_CHALLENGE)(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
245     const struct challenge *self_challenge);
246 static int32_t generate_sign_src_data(const struct hichain *hichain, struct uint8_buff *auth_info,
247     COPY_CHALLENGE copy_func, struct uint8_buff *sign_src_data);
248 static void copy_peer_self_challenge(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
249     const struct challenge *self_challenge);
verify_peer_public_key(const struct hichain * hichain,struct uint8_buff * auth_info,struct signature * sign_result,struct ltpk * ltpk)250 static int32_t verify_peer_public_key(const struct hichain *hichain, struct uint8_buff *auth_info,
251     struct signature *sign_result, struct ltpk *ltpk)
252 {
253     struct uint8_buff sign_src_data;
254     int32_t ret = generate_sign_src_data(hichain, auth_info, copy_peer_self_challenge, &sign_src_data);
255     if (ret != HC_OK) {
256         LOGE("Generate peer signature source data failed, error code is %d", ret);
257         return ret;
258     }
259     enum hc_user_type peer_type = (hichain->type == HC_CENTRE) ? HC_USER_TYPE_ACCESSORY : HC_USER_TYPE_CONTROLLER;
260 
261     ret = verify_with_public_key(peer_type, &sign_src_data, (struct var_buffer *)ltpk, sign_result);
262     FREE(sign_src_data.val);
263     if (ret != HC_OK) {
264         LOGE("Verify peer public key failed, error code is %d", ret);
265         return HC_VERIFY_EXCHANGE_FAILED;
266     }
267     DBG_OUT("Verify peer public key success");
268     return HC_OK;
269 }
270 
271 static void copy_self_peer_challenge(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
272     const struct challenge *self_challenge);
sign_self_public_key(const struct hichain * hichain,struct uint8_buff * auth_info,const struct hc_auth_id * auth_id,struct signature * sign_result)273 static int32_t sign_self_public_key(const struct hichain *hichain, struct uint8_buff *auth_info,
274     const struct hc_auth_id *auth_id, struct signature *sign_result)
275 {
276     struct uint8_buff sign_src_data;
277     int32_t ret = generate_sign_src_data(hichain, auth_info, copy_self_peer_challenge, &sign_src_data);
278     if (ret != HC_OK) {
279         LOGE("Generate self signature source data failed, error code is %d", ret);
280         return ret;
281     }
282 
283     struct service_id service_id = generate_service_id(hichain->pake_client->identity);
284     if (service_id.length == 0) {
285         FREE(sign_src_data.val);
286         LOGE("Generate service id failed");
287         return HC_GEN_SERVICE_ID_FAILED;
288     }
289 #if (defined(_SUPPORT_SEC_CLONE_) || defined(_SUPPORT_SEC_CLONE_SERVER_))
290     struct hc_key_alias alias = generate_key_alias(&service_id, auth_id, KEY_ALIAS_LT_KEY_PAIR);
291 #else
292     struct hc_key_alias alias = generate_key_alias(&service_id, auth_id, KEY_ALIAS_ACCESSOR_PK);
293 #endif
294     if (alias.length == 0) {
295         LOGE("Generate key alias failed");
296         FREE(sign_src_data.val);
297         return HC_SIGN_EXCHANGE_FAILED;
298     }
299     ret = sign(&alias, &sign_src_data, sign_result);
300     FREE(sign_src_data.val);
301     if (ret != HC_OK) {
302         LOGE("Sign self public key failed, error code is %d", ret);
303         return HC_SIGN_EXCHANGE_FAILED;
304     }
305 
306     DBG_OUT("Sign self public key success");
307     return HC_OK;
308 }
309 
build_auth_info(struct uint8_buff * auth_info,const struct hc_auth_id * auth_id,struct ltpk * ltpk)310 static int32_t build_auth_info(struct uint8_buff *auth_info, const struct hc_auth_id *auth_id, struct ltpk *ltpk)
311 {
312     struct exchange_auth_data exchange_auth_data;
313     exchange_auth_data.auth_id = *auth_id;
314     exchange_auth_data.ltpk = *ltpk;
315     auth_info->val = (uint8_t *)make_exchange_data(&exchange_auth_data);
316     if (auth_info->val == NULL) {
317         LOGE("Make exchange data failed");
318         return HC_BUILD_OBJECT_FAILED;
319     }
320     uint32_t tmp_len = strlen((char *)auth_info->val);
321     auth_info->length = tmp_len;
322     auth_info->size = tmp_len;
323     return HC_OK;
324 }
325 
parse_auth_info(const struct uint8_buff * auth_info,struct hc_auth_id * auth_id,struct ltpk * ltpk)326 static int32_t parse_auth_info(const struct uint8_buff *auth_info, struct hc_auth_id *auth_id, struct ltpk *ltpk)
327 {
328     struct exchange_auth_data *auth_data = parse_exchange_data((char *)auth_info->val, JSON_STRING_DATA);
329     if (auth_data == NULL) {
330         LOGE("Parse auth info failed");
331         return HC_DECRYPT_FAILED;
332     }
333     *auth_id = auth_data->auth_id;
334     *ltpk = auth_data->ltpk;
335     free_exchange_data(auth_data);
336     return HC_OK;
337 }
338 
copy_peer_self_challenge(struct uint8_buff * sign_src_data,const struct challenge * peer_challenge,const struct challenge * self_challenge)339 static void copy_peer_self_challenge(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
340     const struct challenge *self_challenge)
341 {
342     if (memcpy_s(sign_src_data->val, sign_src_data->size, peer_challenge->challenge, CHALLENGE_BUFF_LENGTH) != EOK) {
343         FREE(sign_src_data->val);
344         sign_src_data->size = 0;
345         return;
346     }
347     sign_src_data->length += CHALLENGE_BUFF_LENGTH;
348     if (memcpy_s(sign_src_data->val + sign_src_data->length, sign_src_data->size - sign_src_data->length,
349                  self_challenge->challenge, CHALLENGE_BUFF_LENGTH) != EOK) {
350         FREE(sign_src_data->val);
351         sign_src_data->size = 0;
352         return;
353     }
354     sign_src_data->length += CHALLENGE_BUFF_LENGTH;
355 }
356 
copy_self_peer_challenge(struct uint8_buff * sign_src_data,const struct challenge * peer_challenge,const struct challenge * self_challenge)357 static void copy_self_peer_challenge(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
358     const struct challenge *self_challenge)
359 {
360     if (memcpy_s(sign_src_data->val, sign_src_data->size, self_challenge->challenge, CHALLENGE_BUFF_LENGTH) != EOK) {
361         FREE(sign_src_data->val);
362         sign_src_data->size = 0;
363         return;
364     }
365     sign_src_data->length += CHALLENGE_BUFF_LENGTH;
366     if (memcpy_s(sign_src_data->val + sign_src_data->length, sign_src_data->size - sign_src_data->length,
367                  peer_challenge->challenge, CHALLENGE_BUFF_LENGTH) != EOK) {
368         FREE(sign_src_data->val);
369         sign_src_data->size = 0;
370         return;
371     }
372     sign_src_data->length += CHALLENGE_BUFF_LENGTH;
373 }
374 
generate_sign_src_data(const struct hichain * hichain,struct uint8_buff * auth_info,COPY_CHALLENGE copy_func,struct uint8_buff * sign_src_data)375 static int32_t generate_sign_src_data(const struct hichain *hichain, struct uint8_buff *auth_info,
376                                       COPY_CHALLENGE copy_func, struct uint8_buff *sign_src_data)
377 {
378     const struct challenge *peer_challenge = &hichain->pake_client->peer_challenge;
379     const struct challenge *self_challenge = &hichain->pake_client->self_challenge;
380 
381     if ((peer_challenge == NULL) || (self_challenge == NULL)) {
382         LOGE("Get pake challenge failed");
383         return HC_PAKE_OBJECT_ERROR;
384     }
385     sign_src_data->size = CHALLENGE_BUFF_LENGTH + CHALLENGE_BUFF_LENGTH + auth_info->length;
386     sign_src_data->length = 0;
387     sign_src_data->val = (uint8_t *)MALLOC(sign_src_data->size);
388     if (sign_src_data->val == NULL) {
389         LOGE("Malloc failed");
390         sign_src_data->size = 0;
391         return HC_MALLOC_FAILED;
392     }
393     copy_func(sign_src_data, peer_challenge, self_challenge);
394     if (sign_src_data->size == 0) {
395         LOGE("Copy failed");
396         return HC_MEMCPY_ERROR;
397     }
398     (void)memcpy_s(sign_src_data->val + sign_src_data->length, sign_src_data->size - sign_src_data->length,
399                    auth_info->val, auth_info->length);
400     sign_src_data->length += auth_info->length;
401     DBG_OUT("Generate peer sign src data success");
402     return HC_OK;
403 }
404 
405 #else /* _CUT_XXX_ */
406 #include "exchange_auth_info_client.h"
407 #include "log.h"
408 
send_exchange_request(const struct hichain * hichain,struct message * send)409 int32_t send_exchange_request(const struct hichain *hichain, struct message *send)
410 {
411     LOGE("Donot support exchange client for add");
412     (void)hichain;
413     (void)send;
414     return HC_UNSUPPORT;
415 }
416 #endif /* _CUT_XXX_ */
417