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