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(&params->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(&params->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(&params->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(&params->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, &params->sharedSecret);
274     } else if (((uint32_t)params->supportedPakeAlg & PAKE_ALG_DL) != 0) {
275         res = AgreeDlSharedSecret(params, &params->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(&params->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