• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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         FREE(plain.val);
111         return ret;
112     }
113     struct uint8_buff *auth_info = &plain;
114     ret = verify_peer_public_key(hichain, auth_info, &sign_result, &cache->ltpk);
115     FREE(plain.val);
116     if (ret != HC_OK) {
117         LOGE("Verify exchange request message failed, error code is %d", ret);
118         return ret;
119     }
120 
121     return HC_OK;
122 }
123 
124 static int32_t build_auth_info(struct uint8_buff *auth_info, const struct hc_auth_id *auth_id, struct ltpk *ltpk);
125 static int32_t sign_self_public_key(const struct hichain *hichain, struct uint8_buff *auth_info,
126     const struct hc_auth_id *auth_id, struct signature *sign_result);
127 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)128 static int32_t build_exchange_request(const struct hichain *hichain, exchange_request_data *send)
129 {
130     const struct hc_auth_id *auth_id = &hichain->pake_client->self_id;
131     struct ltpk ltpk;
132     int32_t ret = get_self_key_id(hichain, auth_id, &ltpk);
133     if (ret != HC_OK) {
134         LOGE("Get ltpk failed, error code is %d", ret);
135         return ret;
136     }
137 
138     struct uint8_buff auth_info = { NULL, 0, 0 };
139     ret = build_auth_info(&auth_info, auth_id, &ltpk);
140     if (ret != HC_OK) {
141         return HC_BUILD_OBJECT_FAILED;
142     }
143     struct signature sign_result = { 0, {0} };
144     ret = sign_self_public_key(hichain, &auth_info, auth_id, &sign_result);
145     if (ret != HC_OK) {
146         FREE(auth_info.val);
147         LOGE("Sign self public key failed, error code is %d", ret);
148         return ret;
149     }
150 
151     struct uint8_buff plain;
152     plain.size = auth_info.length + sign_result.length;
153     plain.val = (uint8_t *)MALLOC(plain.size);
154     if (plain.val == NULL) {
155         FREE(auth_info.val);
156         return HC_MALLOC_FAILED;
157     }
158     (void)memset_s(plain.val, plain.size, 0, plain.size);
159     if (memcpy_s(plain.val, plain.size, auth_info.val, auth_info.length) != EOK) {
160         FREE(auth_info.val);
161         FREE(plain.val);
162         return memory_copy_error(__func__, __LINE__);
163     }
164     plain.length = auth_info.length;
165     FREE(auth_info.val);
166     if (memcpy_s(plain.val + plain.length, plain.size - plain.length, sign_result.signature, sign_result.length)
167         != EOK) {
168         FREE(plain.val);
169         return memory_copy_error(__func__, __LINE__);
170     }
171     plain.length += sign_result.length;
172 
173     const struct pake_session_key *key = &hichain->pake_client->session_key;
174     ret = encrypt_payload((struct var_buffer *)key, &plain, HICHAIN_EXCHANGE_REQUEST, &send->cipher);
175     FREE(plain.val);
176     if (ret != HC_OK) {
177         LOGE("Encrypt payload failed, error code is %d", ret);
178         return HC_ENCRYPT_FAILED;
179     }
180 
181     return HC_OK;
182 }
183 
get_self_key_id(const struct hichain * hichain,const struct hc_auth_id * auth_id,struct ltpk * ltpk)184 static int32_t get_self_key_id(const struct hichain *hichain, const struct hc_auth_id *auth_id, struct ltpk *ltpk)
185 {
186     struct service_id service_id = generate_service_id(&hichain->identity);
187     if (service_id.length == 0) {
188         LOGE("Generate service id failed");
189         return HC_GEN_SERVICE_ID_FAILED;
190     }
191 #if (defined(_SUPPORT_SEC_CLONE_) || defined(_SUPPORT_SEC_CLONE_SERVER_))
192     struct hc_key_alias alias = generate_key_alias(&service_id, auth_id, KEY_ALIAS_LT_KEY_PAIR);
193 #else
194     struct hc_key_alias alias = generate_key_alias(&service_id, auth_id, KEY_ALIAS_ACCESSOR_PK);
195 #endif
196     if (alias.length == 0) {
197         LOGE("Generate key alias failed");
198         return HC_GEN_ALIAS_FAILED;
199     }
200     int32_t ret = check_lt_public_key_exist(&alias);
201     if (ret != HC_OK) {
202         ret = generate_lt_key_pair(&alias, auth_id);
203         if (ret != HC_OK) {
204             LOGE("Generate self ltpk return value is %d", ret);
205             return HC_GET_LTPK_FAILED;
206         }
207     }
208 
209     ret = export_lt_public_key(&alias, ltpk);
210     if (ret != HC_OK) {
211         LOGE("Get self ltpk failed, error code is %d", ret);
212         return HC_GET_LTPK_FAILED;
213     }
214     DBG_OUT("Get ltpk success");
215     return HC_OK;
216 }
217 
218 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)219 static int32_t get_field_from_request_payload(struct uint8_buff *payload, struct signature *sign_result,
220     struct hc_auth_id *auth_id, struct ltpk *ltpk)
221 {
222     if (payload->length <= HC_SIGNATURE_LEN) {
223         LOGE("Peer public key signature info length is %d", payload->length);
224         return HC_SIGN_TOO_SHORT;
225     }
226     struct uint8_buff *auth_info = payload;
227 
228     auth_info->length -= HC_SIGNATURE_LEN;
229     (void)memcpy_s(sign_result->signature, sizeof(sign_result->signature),
230                    auth_info->val + auth_info->length, HC_SIGNATURE_LEN);
231     sign_result->length = HC_SIGNATURE_LEN;
232     auth_info->val[auth_info->length] = 0;
233     int32_t ret = parse_auth_info(auth_info, auth_id, ltpk);
234     if (ret != HC_OK) {
235         LOGE("Get auth id & ltpk failed, error code is %d", ret);
236         return ret;
237     }
238 
239     return HC_OK;
240 }
241 
242 typedef void (*COPY_CHALLENGE)(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
243     const struct challenge *self_challenge);
244 static int32_t generate_sign_src_data(const struct hichain *hichain, struct uint8_buff *auth_info,
245     COPY_CHALLENGE copy_func, struct uint8_buff *sign_src_data);
246 static void copy_peer_self_challenge(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
247     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)248 static int32_t verify_peer_public_key(const struct hichain *hichain, struct uint8_buff *auth_info,
249     struct signature *sign_result, struct ltpk *ltpk)
250 {
251     struct uint8_buff sign_src_data;
252     int32_t ret = generate_sign_src_data(hichain, auth_info, copy_peer_self_challenge, &sign_src_data);
253     if (ret != HC_OK) {
254         LOGE("Generate peer signature source data failed, error code is %d", ret);
255         return ret;
256     }
257     enum hc_user_type peer_type = (hichain->type == HC_CENTRE) ? HC_USER_TYPE_ACCESSORY : HC_USER_TYPE_CONTROLLER;
258 
259     ret = verify_with_public_key(peer_type, &sign_src_data, (struct var_buffer *)ltpk, sign_result);
260     FREE(sign_src_data.val);
261     if (ret != HC_OK) {
262         LOGE("Verify peer public key failed, error code is %d", ret);
263         return HC_VERIFY_EXCHANGE_FAILED;
264     }
265     DBG_OUT("Verify peer public key success");
266     return HC_OK;
267 }
268 
269 static void copy_self_peer_challenge(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
270     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)271 static int32_t sign_self_public_key(const struct hichain *hichain, struct uint8_buff *auth_info,
272     const struct hc_auth_id *auth_id, struct signature *sign_result)
273 {
274     struct uint8_buff sign_src_data;
275     int32_t ret = generate_sign_src_data(hichain, auth_info, copy_self_peer_challenge, &sign_src_data);
276     if (ret != HC_OK) {
277         LOGE("Generate self signature source data failed, error code is %d", ret);
278         return ret;
279     }
280 
281     struct service_id service_id = generate_service_id(hichain->pake_client->identity);
282     if (service_id.length == 0) {
283         FREE(sign_src_data.val);
284         LOGE("Generate service id failed");
285         return HC_GEN_SERVICE_ID_FAILED;
286     }
287 #if (defined(_SUPPORT_SEC_CLONE_) || defined(_SUPPORT_SEC_CLONE_SERVER_))
288     struct hc_key_alias alias = generate_key_alias(&service_id, auth_id, KEY_ALIAS_LT_KEY_PAIR);
289 #else
290     struct hc_key_alias alias = generate_key_alias(&service_id, auth_id, KEY_ALIAS_ACCESSOR_PK);
291 #endif
292     if (alias.length == 0) {
293         LOGE("Generate key alias failed");
294         FREE(sign_src_data.val);
295         return HC_SIGN_EXCHANGE_FAILED;
296     }
297     ret = sign(&alias, &sign_src_data, sign_result);
298     FREE(sign_src_data.val);
299     if (ret != HC_OK) {
300         LOGE("Sign self public key failed, error code is %d", ret);
301         return HC_SIGN_EXCHANGE_FAILED;
302     }
303 
304     DBG_OUT("Sign self public key success");
305     return HC_OK;
306 }
307 
build_auth_info(struct uint8_buff * auth_info,const struct hc_auth_id * auth_id,struct ltpk * ltpk)308 static int32_t build_auth_info(struct uint8_buff *auth_info, const struct hc_auth_id *auth_id, struct ltpk *ltpk)
309 {
310     struct exchange_auth_data exchange_auth_data;
311     exchange_auth_data.auth_id = *auth_id;
312     exchange_auth_data.ltpk = *ltpk;
313     auth_info->val = (uint8_t *)make_exchange_data(&exchange_auth_data);
314     if (auth_info->val == NULL) {
315         LOGE("Make exchange data failed");
316         return HC_BUILD_OBJECT_FAILED;
317     }
318     uint32_t tmp_len = strlen((char *)auth_info->val);
319     auth_info->length = tmp_len;
320     auth_info->size = tmp_len;
321     return HC_OK;
322 }
323 
parse_auth_info(const struct uint8_buff * auth_info,struct hc_auth_id * auth_id,struct ltpk * ltpk)324 static int32_t parse_auth_info(const struct uint8_buff *auth_info, struct hc_auth_id *auth_id, struct ltpk *ltpk)
325 {
326     struct exchange_auth_data *auth_data = parse_exchange_data((char *)auth_info->val, JSON_STRING_DATA);
327     if (auth_data == NULL) {
328         LOGE("Parse auth info failed");
329         return HC_DECRYPT_FAILED;
330     }
331     *auth_id = auth_data->auth_id;
332     *ltpk = auth_data->ltpk;
333     free_exchange_data(auth_data);
334     return HC_OK;
335 }
336 
copy_peer_self_challenge(struct uint8_buff * sign_src_data,const struct challenge * peer_challenge,const struct challenge * self_challenge)337 static void copy_peer_self_challenge(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
338     const struct challenge *self_challenge)
339 {
340     if (memcpy_s(sign_src_data->val, sign_src_data->size, peer_challenge->challenge, CHALLENGE_BUFF_LENGTH) != EOK) {
341         FREE(sign_src_data->val);
342         sign_src_data->size = 0;
343         return;
344     }
345     sign_src_data->length += CHALLENGE_BUFF_LENGTH;
346     if (memcpy_s(sign_src_data->val + sign_src_data->length, sign_src_data->size - sign_src_data->length,
347                  self_challenge->challenge, CHALLENGE_BUFF_LENGTH) != EOK) {
348         FREE(sign_src_data->val);
349         sign_src_data->size = 0;
350         return;
351     }
352     sign_src_data->length += CHALLENGE_BUFF_LENGTH;
353 }
354 
copy_self_peer_challenge(struct uint8_buff * sign_src_data,const struct challenge * peer_challenge,const struct challenge * self_challenge)355 static void copy_self_peer_challenge(struct uint8_buff *sign_src_data, const struct challenge *peer_challenge,
356     const struct challenge *self_challenge)
357 {
358     if (memcpy_s(sign_src_data->val, sign_src_data->size, self_challenge->challenge, CHALLENGE_BUFF_LENGTH) != EOK) {
359         FREE(sign_src_data->val);
360         sign_src_data->size = 0;
361         return;
362     }
363     sign_src_data->length += CHALLENGE_BUFF_LENGTH;
364     if (memcpy_s(sign_src_data->val + sign_src_data->length, sign_src_data->size - sign_src_data->length,
365                  peer_challenge->challenge, CHALLENGE_BUFF_LENGTH) != EOK) {
366         FREE(sign_src_data->val);
367         sign_src_data->size = 0;
368         return;
369     }
370     sign_src_data->length += CHALLENGE_BUFF_LENGTH;
371 }
372 
generate_sign_src_data(const struct hichain * hichain,struct uint8_buff * auth_info,COPY_CHALLENGE copy_func,struct uint8_buff * sign_src_data)373 static int32_t generate_sign_src_data(const struct hichain *hichain, struct uint8_buff *auth_info,
374                                       COPY_CHALLENGE copy_func, struct uint8_buff *sign_src_data)
375 {
376     const struct challenge *peer_challenge = &hichain->pake_client->peer_challenge;
377     const struct challenge *self_challenge = &hichain->pake_client->self_challenge;
378 
379     if ((peer_challenge == NULL) || (self_challenge == NULL)) {
380         LOGE("Get pake challenge failed");
381         return HC_PAKE_OBJECT_ERROR;
382     }
383     sign_src_data->size = CHALLENGE_BUFF_LENGTH + CHALLENGE_BUFF_LENGTH + auth_info->length;
384     sign_src_data->length = 0;
385     sign_src_data->val = (uint8_t *)MALLOC(sign_src_data->size);
386     if (sign_src_data->val == NULL) {
387         LOGE("Malloc failed");
388         sign_src_data->size = 0;
389         return HC_MALLOC_FAILED;
390     }
391     copy_func(sign_src_data, peer_challenge, self_challenge);
392     if (sign_src_data->size == 0) {
393         LOGE("Copy failed");
394         return HC_MEMCPY_ERROR;
395     }
396     (void)memcpy_s(sign_src_data->val + sign_src_data->length, sign_src_data->size - sign_src_data->length,
397                    auth_info->val, auth_info->length);
398     sign_src_data->length += auth_info->length;
399     DBG_OUT("Generate peer sign src data success");
400     return HC_OK;
401 }
402 
403 #else /* _CUT_XXX_ */
404 #include "exchange_auth_info_client.h"
405 #include "log.h"
406 
send_exchange_request(const struct hichain * hichain,struct message * send)407 int32_t send_exchange_request(const struct hichain *hichain, struct message *send)
408 {
409     LOGE("Donot support exchange client for add");
410     (void)hichain;
411     (void)send;
412     return HC_UNSUPPORT;
413 }
414 #endif /* _CUT_XXX_ */
415