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