1 /*
2 * Copyright (C) 2021 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_v1_protocol_common.h"
17 #include "alg_loader.h"
18 #include "device_auth_defines.h"
19 #include "hc_log.h"
20 #include "hc_types.h"
21 #include "pake_defs.h"
22 #include "pake_protocol_dl_common.h"
23 #include "pake_protocol_ec_common.h"
24 #include "protocol_common.h"
25 #include "string_util.h"
26
27 #define PAKE_SESSION_KEY_LEN 16
28
DestroyPakeV1BaseParams(PakeBaseParams * params)29 void DestroyPakeV1BaseParams(PakeBaseParams *params)
30 {
31 if (params == NULL) {
32 return;
33 }
34
35 CleanPakeSensitiveKeys(params);
36
37 HcFree(params->salt.val);
38 params->salt.val = NULL;
39
40 HcFree(params->challengeSelf.val);
41 params->challengeSelf.val = NULL;
42
43 HcFree(params->challengePeer.val);
44 params->challengePeer.val = NULL;
45
46 HcFree(params->epkSelf.val);
47 params->epkSelf.val = NULL;
48
49 HcFree(params->epkPeer.val);
50 params->epkPeer.val = NULL;
51
52 HcFree(params->kcfData.val);
53 params->kcfData.val = NULL;
54
55 HcFree(params->kcfDataPeer.val);
56 params->kcfDataPeer.val = NULL;
57
58 HcFree(params->idSelf.val);
59 params->idSelf.val = NULL;
60
61 HcFree(params->idPeer.val);
62 params->idPeer.val = NULL;
63
64 HcFree(params->extraData.val);
65 params->extraData.val = NULL;
66 }
67
AllocDefaultParams(PakeBaseParams * params)68 static int32_t AllocDefaultParams(PakeBaseParams *params)
69 {
70 params->salt.length = PAKE_SALT_LEN;
71 params->salt.val = (uint8_t *)HcMalloc(params->salt.length, 0);
72 if (params->salt.val == NULL) {
73 LOGE("Malloc for salt failed.");
74 return HC_ERR_ALLOC_MEMORY;
75 }
76
77 params->challengeSelf.length = PAKE_CHALLENGE_LEN;
78 params->challengeSelf.val = (uint8_t *)HcMalloc(params->challengeSelf.length, 0);
79 if (params->challengeSelf.val == NULL) {
80 LOGE("Malloc for challengeSelf failed.");
81 return HC_ERR_ALLOC_MEMORY;
82 }
83
84 params->challengePeer.length = PAKE_CHALLENGE_LEN;
85 params->challengePeer.val = (uint8_t *)HcMalloc(params->challengePeer.length, 0);
86 if (params->challengePeer.val == NULL) {
87 LOGE("Malloc for challengePeer failed.");
88 return HC_ERR_ALLOC_MEMORY;
89 }
90
91 params->sessionKey.length = PAKE_SESSION_KEY_LEN;
92 params->sessionKey.val = (uint8_t *)HcMalloc(params->sessionKey.length, 0);
93 if (params->sessionKey.val == NULL) {
94 LOGE("Malloc for sessionKey failed.");
95 return HC_ERR_ALLOC_MEMORY;
96 }
97
98 params->hmacKey.length = PAKE_HMAC_KEY_LEN;
99 params->hmacKey.val = (uint8_t *)HcMalloc(params->hmacKey.length, 0);
100 if (params->hmacKey.val == NULL) {
101 LOGE("Malloc for hmacKey failed.");
102 return HC_ERR_ALLOC_MEMORY;
103 }
104
105 params->kcfData.length = HMAC_LEN;
106 params->kcfData.val = (uint8_t *)HcMalloc(params->kcfData.length, 0);
107 if (params->kcfData.val == NULL) {
108 LOGE("Malloc for kcfData failed.");
109 return HC_ERR_ALLOC_MEMORY;
110 }
111
112 params->kcfDataPeer.length = HMAC_LEN;
113 params->kcfDataPeer.val = (uint8_t *)HcMalloc(params->kcfDataPeer.length, 0);
114 if (params->kcfDataPeer.val == NULL) {
115 LOGE("Malloc for kcfDataPeer failed.");
116 return HC_ERR_ALLOC_MEMORY;
117 }
118 return HC_SUCCESS;
119 }
120
FillDefaultValue(PakeBaseParams * params)121 static void FillDefaultValue(PakeBaseParams *params)
122 {
123 params->psk.val = NULL;
124 params->psk.length = 0;
125 params->eskSelf.val = NULL;
126 params->eskSelf.length = 0;
127 params->epkSelf.val = NULL;
128 params->epkSelf.length = 0;
129 params->epkPeer.val = NULL;
130 params->epkPeer.length = 0;
131 params->base.val = NULL;
132 params->base.length = 0;
133 params->sharedSecret.val = NULL;
134 params->sharedSecret.length = 0;
135 params->idSelf.val = NULL;
136 params->idSelf.length = 0;
137 params->idPeer.val = NULL;
138 params->idPeer.length = 0;
139 params->extraData.val = NULL;
140 params->extraData.length = 0;
141 params->supportedDlPrimeMod = DL_PRIME_MOD_NONE;
142 params->largePrimeNumHex = NULL;
143 params->innerKeyLen = 0;
144 params->supportedPakeAlg = PAKE_ALG_NONE;
145 params->curveType = CURVE_NONE;
146 params->isClient = true;
147 }
148
InitPakeV1BaseParams(int32_t osAccountId,PakeBaseParams * params)149 int32_t InitPakeV1BaseParams(int32_t osAccountId, PakeBaseParams *params)
150 {
151 if (params == NULL) {
152 LOGE("Params is null.");
153 return HC_ERR_NULL_PTR;
154 }
155 params->osAccountId = osAccountId;
156
157 int32_t res = AllocDefaultParams(params);
158 if (res != HC_SUCCESS) {
159 goto CLEAN_UP;
160 }
161
162 FillDefaultValue(params);
163
164 params->loader = GetLoaderInstance();
165 if (params->loader == NULL) {
166 res = HC_ERROR;
167 goto CLEAN_UP;
168 }
169
170 return HC_SUCCESS;
171 CLEAN_UP:
172 DestroyPakeV1BaseParams(params);
173 return res;
174 }
175
GeneratePakeParams(PakeBaseParams * params)176 static int32_t GeneratePakeParams(PakeBaseParams *params)
177 {
178 int32_t res;
179 uint8_t secretVal[PAKE_SECRET_LEN] = { 0 };
180 Uint8Buff secret = { secretVal, PAKE_SECRET_LEN };
181 if (!params->isClient) {
182 res = params->loader->generateRandom(&(params->salt));
183 if (res != HC_SUCCESS) {
184 LOGE("Generate salt failed, res: %" LOG_PUB "x.", res);
185 goto CLEAN_UP;
186 }
187 }
188 PRINT_DEBUG_MSG(params->salt.val, params->salt.length, "saltValue");
189
190 res = params->loader->generateRandom(&(params->challengeSelf));
191 if (res != HC_SUCCESS) {
192 LOGE("Generate challengeSelf failed, res: %" LOG_PUB "x.", res);
193 goto CLEAN_UP;
194 }
195 PRINT_DEBUG_MSG(params->challengeSelf.val, params->challengeSelf.length, "challengeSelf");
196
197 Uint8Buff keyInfo = { (uint8_t *)HICHAIN_SPEKE_BASE_INFO, HcStrlen(HICHAIN_SPEKE_BASE_INFO) };
198 KeyParams keyParams = { { params->psk.val, params->psk.length, false }, false, params->osAccountId };
199 res = params->loader->computeHkdf(&keyParams, &(params->salt), &keyInfo, &secret);
200 PRINT_SENSITIVE_DATA("pskValue", (char *)params->psk.val);
201 PRINT_DEBUG_MSG(secret.val, secret.length, "secretValue");
202 if (res != HC_SUCCESS) {
203 LOGE("Derive secret from psk failed, res: %" LOG_PUB "x.", res);
204 goto CLEAN_UP;
205 }
206 FreeAndCleanKey(¶ms->psk);
207
208 if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_EC) != 0) {
209 res = GenerateEcPakeParams(params, &secret);
210 } else if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_DL) != 0) {
211 res = GenerateDlPakeParams(params, &secret);
212 } else {
213 res = HC_ERR_INVALID_ALG;
214 }
215 if (res != HC_SUCCESS) {
216 LOGE("GeneratePakeParams failed, pakeAlgType: 0x%" LOG_PUB "x, res: %" LOG_PUB "x.",
217 params->supportedPakeAlg, res);
218 goto CLEAN_UP;
219 }
220 FreeAndCleanKey(¶ms->base);
221 (void)memset_s(secret.val, secret.length, 0, secret.length);
222 return res;
223 CLEAN_UP:
224 (void)memset_s(secret.val, secret.length, 0, secret.length);
225 CleanPakeSensitiveKeys(params);
226 return res;
227 }
228
DeriveKeyFromSharedSecret(PakeBaseParams * params)229 static int32_t DeriveKeyFromSharedSecret(PakeBaseParams *params)
230 {
231 int32_t res;
232 Uint8Buff unionKey = { NULL, 0 };
233 Uint8Buff keyInfo = { (uint8_t *)HICHAIN_SPEKE_SESSIONKEY_INFO, HcStrlen(HICHAIN_SPEKE_SESSIONKEY_INFO) };
234 unionKey.length = params->sessionKey.length + params->hmacKey.length;
235 unionKey.val = (uint8_t *)HcMalloc(unionKey.length, 0);
236 if (unionKey.val == NULL) {
237 LOGE("Malloc for unionKey failed.");
238 res = HC_ERR_ALLOC_MEMORY;
239 goto CLEAN_UP;
240 }
241
242 KeyParams keyParams = {
243 .keyBuff = { params->sharedSecret.val, params->sharedSecret.length, false },
244 .isDeStorage = false,
245 .osAccountId = params->osAccountId
246 };
247 res = params->loader->computeHkdf(&keyParams, &(params->salt), &keyInfo, &unionKey);
248 if (res != HC_SUCCESS) {
249 LOGE("ComputeHkdf for unionKey failed, res: %" LOG_PUB "x.", res);
250 goto CLEAN_UP;
251 }
252 PRINT_DEBUG_MSG(unionKey.val, unionKey.length, "unionKey");
253 FreeAndCleanKey(¶ms->sharedSecret);
254 if (memcpy_s(params->sessionKey.val, params->sessionKey.length, unionKey.val, params->sessionKey.length) != EOK) {
255 LOGE("Memcpy for sessionKey failed.");
256 res = HC_ERR_ALLOC_MEMORY;
257 goto CLEAN_UP;
258 }
259 PRINT_DEBUG_MSG(params->sessionKey.val, params->sessionKey.length, "sessionKey");
260 if (memcpy_s(params->hmacKey.val, params->hmacKey.length,
261 unionKey.val + params->sessionKey.length, params->hmacKey.length) != EOK) {
262 LOGE("Memcpy for hmacKey failed.");
263 res = HC_ERR_ALLOC_MEMORY;
264 goto CLEAN_UP;
265 }
266 PRINT_DEBUG_MSG(params->hmacKey.val, params->hmacKey.length, "hmacKey");
267 CLEAN_UP:
268 FreeAndCleanKey(&unionKey);
269 return res;
270 }
271
GenerateSessionKey(PakeBaseParams * params)272 static int32_t GenerateSessionKey(PakeBaseParams *params)
273 {
274 int32_t res = InitSingleParam(¶ms->sharedSecret, params->innerKeyLen);
275 if (res != HC_SUCCESS) {
276 LOGE("InitSingleParam for sharedSecret failed, res: %" LOG_PUB "x.", res);
277 goto CLEAN_UP;
278 }
279
280 if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_EC) != 0) {
281 res = AgreeEcSharedSecret(params, ¶ms->sharedSecret);
282 } else if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_DL) != 0) {
283 res = AgreeDlSharedSecret(params, ¶ms->sharedSecret);
284 } else {
285 res = HC_ERR_INVALID_ALG;
286 }
287 if (res != HC_SUCCESS) {
288 LOGE("AgreeDlSharedSecret failed, pakeAlgType: 0x%" LOG_PUB "x, res: %" LOG_PUB "x.",
289 params->supportedPakeAlg, res);
290 goto CLEAN_UP;
291 }
292 FreeAndCleanKey(¶ms->eskSelf);
293
294 res = DeriveKeyFromSharedSecret(params);
295 if (res != HC_SUCCESS) {
296 LOGE("DeriveKeyFromSharedSecret failed, res: %" LOG_PUB "x.", res);
297 goto CLEAN_UP;
298 }
299 return res;
300 CLEAN_UP:
301 CleanPakeSensitiveKeys(params);
302 return res;
303 }
304
GenerateProof(PakeBaseParams * params)305 static int32_t GenerateProof(PakeBaseParams *params)
306 {
307 int res;
308 uint8_t challengeVal[PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN] = { 0 };
309 Uint8Buff challenge = { challengeVal, PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN };
310 if (memcpy_s(challenge.val, challenge.length, params->challengeSelf.val, params->challengeSelf.length) != EOK) {
311 LOGE("Memcpy challengeSelf failed.");
312 res = HC_ERR_MEMORY_COPY;
313 goto CLEAN_UP;
314 }
315 PRINT_DEBUG_MSG(params->challengePeer.val, params->challengePeer.length, "challengePeer");
316 if (memcpy_s(challenge.val + params->challengeSelf.length, challenge.length - params->challengeSelf.length,
317 params->challengePeer.val, params->challengePeer.length) != EOK) {
318 LOGE("Memcpy challengePeer failed.");
319 res = HC_ERR_MEMORY_COPY;
320 goto CLEAN_UP;
321 }
322 PRINT_DEBUG_MSG(challenge.val, challenge.length, "challenge");
323
324 KeyParams keyParams = { { params->hmacKey.val, params->hmacKey.length, false }, false, params->osAccountId };
325 res = params->loader->computeHmac(&keyParams, &challenge, &(params->kcfData));
326 if (res != HC_SUCCESS) {
327 LOGE("Compute hmac for kcfData failed, res: %" LOG_PUB "x.", res);
328 goto CLEAN_UP;
329 }
330 PRINT_DEBUG_MSG(params->kcfData.val, params->kcfData.length, "kcfData");
331 return res;
332 CLEAN_UP:
333 CleanPakeSensitiveKeys(params);
334 return res;
335 }
336
VerifyProof(PakeBaseParams * params)337 static int32_t VerifyProof(PakeBaseParams *params)
338 {
339 uint8_t challengeVal[PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN] = { 0 };
340 Uint8Buff challenge = { challengeVal, PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN };
341 int res;
342 if (memcpy_s(challenge.val, challenge.length, params->challengePeer.val, params->challengePeer.length) != EOK) {
343 LOGE("Memcpy for challengePeer failed.");
344 res = HC_ERR_MEMORY_COPY;
345 goto CLEAN_UP;
346 }
347 if (memcpy_s(challenge.val + params->challengePeer.length, challenge.length - params->challengePeer.length,
348 params->challengeSelf.val, params->challengeSelf.length) != EOK) {
349 LOGE("Memcpy for challengeSelf failed.");
350 res = HC_ERR_MEMORY_COPY;
351 goto CLEAN_UP;
352 }
353 PRINT_DEBUG_MSG(challenge.val, challenge.length, "challenge");
354
355 uint8_t verifyProofVal[HMAC_LEN] = { 0 };
356 Uint8Buff verifyProof = { verifyProofVal, HMAC_LEN };
357 KeyParams keyParams = { { params->hmacKey.val, params->hmacKey.length, false }, false, params->osAccountId };
358 res = params->loader->computeHmac(&keyParams, &challenge, &verifyProof);
359 if (res != HC_SUCCESS) {
360 LOGE("Compute hmac for kcfData failed, res: %" LOG_PUB "x.", res);
361 goto CLEAN_UP;
362 }
363 PRINT_DEBUG_MSG(verifyProof.val, verifyProof.length, "verifyProof");
364
365 if (memcmp(verifyProof.val, params->kcfDataPeer.val, verifyProof.length) != 0) {
366 LOGE("Compare kcfDataPeer failed.");
367 res = PROOF_MISMATCH;
368 goto CLEAN_UP;
369 }
370 return res;
371 CLEAN_UP:
372 CleanPakeSensitiveKeys(params);
373 return res;
374 }
375
ClientConfirmPakeV1Protocol(PakeBaseParams * params)376 int32_t ClientConfirmPakeV1Protocol(PakeBaseParams *params)
377 {
378 if (params == NULL) {
379 LOGE("Params is null.");
380 return HC_ERR_NULL_PTR;
381 }
382 int32_t res = GeneratePakeParams(params);
383 if (res != HC_SUCCESS) {
384 LOGE("GeneratePakeParams failed, res: %" LOG_PUB "x.", res);
385 goto CLEAN_UP;
386 }
387
388 res = GenerateSessionKey(params);
389 if (res != HC_SUCCESS) {
390 LOGE("GenerateSessionKey failed, res: %" LOG_PUB "x.", res);
391 goto CLEAN_UP;
392 }
393
394 res = GenerateProof(params);
395 if (res != HC_SUCCESS) {
396 LOGE("GenerateProof failed, res: %" LOG_PUB "x.", res);
397 goto CLEAN_UP;
398 }
399 return res;
400 CLEAN_UP:
401 CleanPakeSensitiveKeys(params);
402 return res;
403 }
404
ClientVerifyConfirmPakeV1Protocol(PakeBaseParams * params)405 int32_t ClientVerifyConfirmPakeV1Protocol(PakeBaseParams *params)
406 {
407 if (params == NULL) {
408 LOGE("Params is null.");
409 return HC_ERR_NULL_PTR;
410 }
411 int32_t res = VerifyProof(params);
412 if (res != HC_SUCCESS) {
413 LOGE("VerifyProof failed, res: %" LOG_PUB "x.", res);
414 CleanPakeSensitiveKeys(params);
415 }
416 return res;
417 }
418
ServerResponsePakeV1Protocol(PakeBaseParams * params)419 int32_t ServerResponsePakeV1Protocol(PakeBaseParams *params)
420 {
421 if (params == NULL) {
422 LOGE("Params is null.");
423 return HC_ERR_NULL_PTR;
424 }
425 int32_t res = GeneratePakeParams(params);
426 if (res != HC_SUCCESS) {
427 LOGE("GeneratePakeParams failed, res: %" LOG_PUB "x.", res);
428 CleanPakeSensitiveKeys(params);
429 }
430 return res;
431 }
432
ServerConfirmPakeV1Protocol(PakeBaseParams * params)433 int32_t ServerConfirmPakeV1Protocol(PakeBaseParams *params)
434 {
435 if (params == NULL) {
436 LOGE("Params is null.");
437 return HC_ERR_NULL_PTR;
438 }
439 int32_t res = GenerateSessionKey(params);
440 if (res != HC_SUCCESS) {
441 LOGE("GenerateSessionKey failed, res: %" LOG_PUB "x.", res);
442 goto CLEAN_UP;
443 }
444
445 res = VerifyProof(params);
446 if (res != HC_SUCCESS) {
447 LOGE("VerifyProof failed, res: %" LOG_PUB "x.", res);
448 goto CLEAN_UP;
449 }
450
451 res = GenerateProof(params);
452 if (res != HC_SUCCESS) {
453 LOGE("GenerateProof failed, res: %" LOG_PUB "x.", res);
454 goto CLEAN_UP;
455 }
456
457 return res;
458 CLEAN_UP:
459 CleanPakeSensitiveKeys(params);
460 return res;
461 }
462