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, <pk);
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, <pk);
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