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: %x.", res);
185 goto CLEAN_UP;
186 }
187 }
188
189 res = params->loader->generateRandom(&(params->challengeSelf));
190 if (res != HC_SUCCESS) {
191 LOGE("Generate challengeSelf failed, res: %x.", res);
192 goto CLEAN_UP;
193 }
194
195 Uint8Buff keyInfo = { (uint8_t *)HICHAIN_SPEKE_BASE_INFO, HcStrlen(HICHAIN_SPEKE_BASE_INFO) };
196 KeyParams keyParams = { { params->psk.val, params->psk.length, false }, false, params->osAccountId };
197 res = params->loader->computeHkdf(&keyParams, &(params->salt), &keyInfo, &secret);
198 if (res != HC_SUCCESS) {
199 LOGE("Derive secret from psk failed, res: %x.", res);
200 goto CLEAN_UP;
201 }
202 FreeAndCleanKey(¶ms->psk);
203
204 if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_EC) != 0) {
205 res = GenerateEcPakeParams(params, &secret);
206 } else if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_DL) != 0) {
207 res = GenerateDlPakeParams(params, &secret);
208 } else {
209 res = HC_ERR_INVALID_ALG;
210 }
211 if (res != HC_SUCCESS) {
212 LOGE("GeneratePakeParams failed, pakeAlgType: 0x%x, res: %x.", params->supportedPakeAlg, res);
213 goto CLEAN_UP;
214 }
215 FreeAndCleanKey(¶ms->base);
216 (void)memset_s(secret.val, secret.length, 0, secret.length);
217 return res;
218 CLEAN_UP:
219 (void)memset_s(secret.val, secret.length, 0, secret.length);
220 CleanPakeSensitiveKeys(params);
221 return res;
222 }
223
DeriveKeyFromSharedSecret(PakeBaseParams * params)224 static int32_t DeriveKeyFromSharedSecret(PakeBaseParams *params)
225 {
226 int32_t res;
227 Uint8Buff unionKey = { NULL, 0 };
228 Uint8Buff keyInfo = { (uint8_t *)HICHAIN_SPEKE_SESSIONKEY_INFO, HcStrlen(HICHAIN_SPEKE_SESSIONKEY_INFO) };
229 unionKey.length = params->sessionKey.length + params->hmacKey.length;
230 unionKey.val = (uint8_t *)HcMalloc(unionKey.length, 0);
231 if (unionKey.val == NULL) {
232 LOGE("Malloc for unionKey failed.");
233 res = HC_ERR_ALLOC_MEMORY;
234 goto CLEAN_UP;
235 }
236
237 KeyParams keyParams = {
238 .keyBuff = { params->sharedSecret.val, params->sharedSecret.length, false },
239 .isDeStorage = false,
240 .osAccountId = params->osAccountId
241 };
242 res = params->loader->computeHkdf(&keyParams, &(params->salt), &keyInfo, &unionKey);
243 if (res != HC_SUCCESS) {
244 LOGE("ComputeHkdf for unionKey failed, res: %x.", res);
245 goto CLEAN_UP;
246 }
247 FreeAndCleanKey(¶ms->sharedSecret);
248 if (memcpy_s(params->sessionKey.val, params->sessionKey.length, unionKey.val, params->sessionKey.length) != EOK) {
249 LOGE("Memcpy for sessionKey failed.");
250 res = HC_ERR_ALLOC_MEMORY;
251 goto CLEAN_UP;
252 }
253 if (memcpy_s(params->hmacKey.val, params->hmacKey.length,
254 unionKey.val + params->sessionKey.length, params->hmacKey.length) != EOK) {
255 LOGE("Memcpy for hmacKey failed.");
256 res = HC_ERR_ALLOC_MEMORY;
257 goto CLEAN_UP;
258 }
259 CLEAN_UP:
260 FreeAndCleanKey(&unionKey);
261 return res;
262 }
263
GenerateSessionKey(PakeBaseParams * params)264 static int32_t GenerateSessionKey(PakeBaseParams *params)
265 {
266 int32_t res = InitSingleParam(¶ms->sharedSecret, params->innerKeyLen);
267 if (res != HC_SUCCESS) {
268 LOGE("InitSingleParam for sharedSecret failed, res: %x.", res);
269 goto CLEAN_UP;
270 }
271
272 if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_EC) != 0) {
273 res = AgreeEcSharedSecret(params, ¶ms->sharedSecret);
274 } else if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_DL) != 0) {
275 res = AgreeDlSharedSecret(params, ¶ms->sharedSecret);
276 } else {
277 res = HC_ERR_INVALID_ALG;
278 }
279 if (res != HC_SUCCESS) {
280 LOGE("AgreeDlSharedSecret failed, pakeAlgType: 0x%x, res: %x.", params->supportedPakeAlg, res);
281 goto CLEAN_UP;
282 }
283 FreeAndCleanKey(¶ms->eskSelf);
284
285 res = DeriveKeyFromSharedSecret(params);
286 if (res != HC_SUCCESS) {
287 LOGE("DeriveKeyFromSharedSecret failed, res: %x.", res);
288 goto CLEAN_UP;
289 }
290 return res;
291 CLEAN_UP:
292 CleanPakeSensitiveKeys(params);
293 return res;
294 }
295
GenerateProof(PakeBaseParams * params)296 static int32_t GenerateProof(PakeBaseParams *params)
297 {
298 int res;
299 uint8_t challengeVal[PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN] = { 0 };
300 Uint8Buff challenge = { challengeVal, PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN };
301 if (memcpy_s(challenge.val, challenge.length, params->challengeSelf.val, params->challengeSelf.length) != EOK) {
302 LOGE("Memcpy challengeSelf failed.");
303 res = HC_ERR_MEMORY_COPY;
304 goto CLEAN_UP;
305 }
306 if (memcpy_s(challenge.val + params->challengeSelf.length, challenge.length - params->challengeSelf.length,
307 params->challengePeer.val, params->challengePeer.length) != EOK) {
308 LOGE("Memcpy challengePeer failed.");
309 res = HC_ERR_MEMORY_COPY;
310 goto CLEAN_UP;
311 }
312
313 KeyParams keyParams = { { params->hmacKey.val, params->hmacKey.length, false }, false, params->osAccountId };
314 res = params->loader->computeHmac(&keyParams, &challenge, &(params->kcfData));
315 if (res != HC_SUCCESS) {
316 LOGE("Compute hmac for kcfData failed, res: %x.", res);
317 goto CLEAN_UP;
318 }
319 return res;
320 CLEAN_UP:
321 CleanPakeSensitiveKeys(params);
322 return res;
323 }
324
VerifyProof(PakeBaseParams * params)325 static int32_t VerifyProof(PakeBaseParams *params)
326 {
327 uint8_t challengeVal[PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN] = { 0 };
328 Uint8Buff challenge = { challengeVal, PAKE_CHALLENGE_LEN + PAKE_CHALLENGE_LEN };
329 int res;
330 if (memcpy_s(challenge.val, challenge.length, params->challengePeer.val, params->challengePeer.length) != EOK) {
331 LOGE("Memcpy for challengePeer failed.");
332 res = HC_ERR_MEMORY_COPY;
333 goto CLEAN_UP;
334 }
335 if (memcpy_s(challenge.val + params->challengePeer.length, challenge.length - params->challengePeer.length,
336 params->challengeSelf.val, params->challengeSelf.length) != EOK) {
337 LOGE("Memcpy for challengeSelf failed.");
338 res = HC_ERR_MEMORY_COPY;
339 goto CLEAN_UP;
340 }
341
342 uint8_t verifyProofVal[HMAC_LEN] = { 0 };
343 Uint8Buff verifyProof = { verifyProofVal, HMAC_LEN };
344 KeyParams keyParams = { { params->hmacKey.val, params->hmacKey.length, false }, false, params->osAccountId };
345 res = params->loader->computeHmac(&keyParams, &challenge, &verifyProof);
346 if (res != HC_SUCCESS) {
347 LOGE("Compute hmac for kcfData failed, res: %x.", res);
348 goto CLEAN_UP;
349 }
350
351 if (memcmp(verifyProof.val, params->kcfDataPeer.val, verifyProof.length) != 0) {
352 LOGE("Compare kcfDataPeer failed.");
353 res = PROOF_MISMATCH;
354 goto CLEAN_UP;
355 }
356 return res;
357 CLEAN_UP:
358 CleanPakeSensitiveKeys(params);
359 return res;
360 }
361
ClientConfirmPakeV1Protocol(PakeBaseParams * params)362 int32_t ClientConfirmPakeV1Protocol(PakeBaseParams *params)
363 {
364 if (params == NULL) {
365 LOGE("Params is null.");
366 return HC_ERR_NULL_PTR;
367 }
368 int32_t res = GeneratePakeParams(params);
369 if (res != HC_SUCCESS) {
370 LOGE("GeneratePakeParams failed, res: %x.", res);
371 goto CLEAN_UP;
372 }
373
374 res = GenerateSessionKey(params);
375 if (res != HC_SUCCESS) {
376 LOGE("GenerateSessionKey failed, res: %x.", res);
377 goto CLEAN_UP;
378 }
379
380 res = GenerateProof(params);
381 if (res != HC_SUCCESS) {
382 LOGE("GenerateProof failed, res: %x.", res);
383 goto CLEAN_UP;
384 }
385 return res;
386 CLEAN_UP:
387 CleanPakeSensitiveKeys(params);
388 return res;
389 }
390
ClientVerifyConfirmPakeV1Protocol(PakeBaseParams * params)391 int32_t ClientVerifyConfirmPakeV1Protocol(PakeBaseParams *params)
392 {
393 if (params == NULL) {
394 LOGE("Params is null.");
395 return HC_ERR_NULL_PTR;
396 }
397 int32_t res = VerifyProof(params);
398 if (res != HC_SUCCESS) {
399 LOGE("VerifyProof failed, res: %x.", res);
400 CleanPakeSensitiveKeys(params);
401 }
402 return res;
403 }
404
ServerResponsePakeV1Protocol(PakeBaseParams * params)405 int32_t ServerResponsePakeV1Protocol(PakeBaseParams *params)
406 {
407 if (params == NULL) {
408 LOGE("Params is null.");
409 return HC_ERR_NULL_PTR;
410 }
411 int32_t res = GeneratePakeParams(params);
412 if (res != HC_SUCCESS) {
413 LOGE("GeneratePakeParams failed, res: %x.", res);
414 CleanPakeSensitiveKeys(params);
415 }
416 return res;
417 }
418
ServerConfirmPakeV1Protocol(PakeBaseParams * params)419 int32_t ServerConfirmPakeV1Protocol(PakeBaseParams *params)
420 {
421 if (params == NULL) {
422 LOGE("Params is null.");
423 return HC_ERR_NULL_PTR;
424 }
425 int32_t res = GenerateSessionKey(params);
426 if (res != HC_SUCCESS) {
427 LOGE("GenerateSessionKey failed, res: %x.", res);
428 goto CLEAN_UP;
429 }
430
431 res = VerifyProof(params);
432 if (res != HC_SUCCESS) {
433 LOGE("VerifyProof failed, res: %x.", res);
434 goto CLEAN_UP;
435 }
436
437 res = GenerateProof(params);
438 if (res != HC_SUCCESS) {
439 LOGE("GenerateProof failed, res: %x.", res);
440 goto CLEAN_UP;
441 }
442
443 return res;
444 CLEAN_UP:
445 CleanPakeSensitiveKeys(params);
446 return res;
447 }
448