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