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 "iso_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 "protocol_common.h"
22 #include "device_auth.h"
23 
InitIsoBaseParams(const CJson * in,IsoBaseParams * params)24 int32_t InitIsoBaseParams(const CJson *in, IsoBaseParams *params)
25 {
26     if (in == NULL || params == NULL) {
27         LOGE("Params is null.");
28         return HC_ERR_NULL_PTR;
29     }
30     if (GetIntFromJson(in, FIELD_OS_ACCOUNT_ID, &params->osAccountId) != HC_SUCCESS) {
31         LOGE("Failed to get osAccountId!");
32         return HC_ERR_JSON_GET;
33     }
34 
35     int32_t res;
36     params->randSelf.length = RAND_BYTE_LEN;
37     params->randSelf.val = (uint8_t *)HcMalloc(params->randSelf.length, 0);
38     if (params->randSelf.val == NULL) {
39         LOGE("Malloc randSelf failed.");
40         res = HC_ERR_ALLOC_MEMORY;
41         goto CLEAN_UP;
42     }
43     params->randPeer.length = RAND_BYTE_LEN;
44     params->randPeer.val = (uint8_t *)HcMalloc(params->randPeer.length, 0);
45     if (params->randPeer.val == NULL) {
46         LOGE("Malloc randPeer failed.");
47         res = HC_ERR_ALLOC_MEMORY;
48         goto CLEAN_UP;
49     }
50 
51     params->sessionKey.length = ISO_SESSION_KEY_LEN;
52     params->sessionKey.val = (uint8_t *)HcMalloc(params->sessionKey.length, 0);
53     if (params->sessionKey.val == NULL) {
54         LOGE("Malloc sessionKey failed.");
55         res = HC_ERR_ALLOC_MEMORY;
56         goto CLEAN_UP;
57     }
58 
59     params->loader = GetLoaderInstance();
60     if (params->loader == NULL) {
61         res = HC_ERROR;
62         goto CLEAN_UP;
63     }
64 
65     return HC_SUCCESS;
66 CLEAN_UP:
67     DestroyIsoBaseParams(params);
68     return res;
69 }
70 
DestroyIsoBaseParams(IsoBaseParams * params)71 void DestroyIsoBaseParams(IsoBaseParams *params)
72 {
73     if (params == NULL) {
74         return;
75     }
76 
77     FreeAndCleanKey(&params->sessionKey);
78     (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
79 
80     HcFree(params->randSelf.val);
81     params->randSelf.val = NULL;
82 
83     HcFree(params->randPeer.val);
84     params->randPeer.val = NULL;
85 
86     HcFree(params->authIdSelf.val);
87     params->authIdSelf.val = NULL;
88 
89     HcFree(params->authIdPeer.val);
90     params->authIdPeer.val = NULL;
91 }
92 
IsoCalSelfToken(const IsoBaseParams * params,Uint8Buff * outHmac)93 static int IsoCalSelfToken(const IsoBaseParams *params, Uint8Buff *outHmac)
94 {
95     int res;
96     int length = params->randSelf.length + params->randPeer.length + params->authIdSelf.length +
97         params->authIdPeer.length;
98     uint8_t *messagePeer = (uint8_t *)HcMalloc(length, 0);
99     if (messagePeer == NULL) {
100         LOGE("Malloc for messagePeer failed.");
101         return HC_ERR_ALLOC_MEMORY;
102     }
103     int usedLen = 0;
104     if (memcpy_s(messagePeer, length, params->randPeer.val, params->randPeer.length) != EOK) {
105         LOGE("Memcpy randPeer failed.");
106         res = HC_ERR_MEMORY_COPY;
107         goto CLEAN_UP;
108     }
109     usedLen += params->randPeer.length;
110     if (memcpy_s(messagePeer + usedLen, length - usedLen, params->randSelf.val, params->randSelf.length) != EOK) {
111         LOGE("Memcpy randSelf failed.");
112         res = HC_ERR_MEMORY_COPY;
113         goto CLEAN_UP;
114     }
115     usedLen += params->randSelf.length;
116     if (memcpy_s(messagePeer + usedLen, length - usedLen, params->authIdSelf.val, params->authIdSelf.length) != EOK) {
117         LOGE("Memcpy authIdSelf failed.");
118         res = HC_ERR_MEMORY_COPY;
119         goto CLEAN_UP;
120     }
121     usedLen += params->authIdSelf.length;
122     if (memcpy_s(messagePeer + usedLen, length - usedLen, params->authIdPeer.val, params->authIdPeer.length) != EOK) {
123         LOGE("Memcpy authIdPeer failed.");
124         res = HC_ERR_MEMORY_COPY;
125         goto CLEAN_UP;
126     }
127     Uint8Buff messageBuf = { messagePeer, length };
128     Uint8Buff pskBuf = { (uint8_t *)params->psk, sizeof(params->psk) };
129     KeyParams keyParams = { { pskBuf.val, pskBuf.length, false }, false, params->osAccountId };
130     res = params->loader->computeHmac(&keyParams, &messageBuf, outHmac);
131     if (res != HC_SUCCESS) {
132         LOGE("ComputeHmac failed, res: %x.", res);
133         goto CLEAN_UP;
134     }
135 CLEAN_UP:
136     HcFree(messagePeer);
137     return res;
138 }
139 
IsoCalPeerToken(const IsoBaseParams * params,Uint8Buff * selfToken)140 static int IsoCalPeerToken(const IsoBaseParams *params, Uint8Buff *selfToken)
141 {
142     int length = params->randSelf.length + params->randPeer.length + params->authIdPeer.length +
143         params->authIdSelf.length;
144     uint8_t *messageSelf = (uint8_t *)HcMalloc(length, 0);
145     if (messageSelf == NULL) {
146         LOGE("Malloc for messageSelf failed.");
147         return HC_ERR_ALLOC_MEMORY;
148     }
149     int res;
150     int usedLen = 0;
151     if (memcpy_s(messageSelf, length, params->randSelf.val, params->randSelf.length) != EOK) {
152         LOGE("Memcpy randSelf failed.");
153         res = HC_ERR_MEMORY_COPY;
154         goto CLEAN_UP;
155     }
156     usedLen += params->randSelf.length;
157     if (memcpy_s(messageSelf + usedLen, length - usedLen, params->randPeer.val, params->randPeer.length) != EOK) {
158         LOGE("Memcpy randPeer failed.");
159         res = HC_ERR_MEMORY_COPY;
160         goto CLEAN_UP;
161     }
162     usedLen += params->randPeer.length;
163     if (memcpy_s(messageSelf + usedLen, length - usedLen, params->authIdPeer.val, params->authIdPeer.length) != EOK) {
164         LOGE("Memcpy authIdPeer failed.");
165         res = HC_ERR_MEMORY_COPY;
166         goto CLEAN_UP;
167     }
168     usedLen += params->authIdPeer.length;
169     if (memcpy_s(messageSelf + usedLen, length - usedLen, params->authIdSelf.val, params->authIdSelf.length) != EOK) {
170         LOGE("Memcpy authIdSelf failed.");
171         res = HC_ERR_MEMORY_COPY;
172         goto CLEAN_UP;
173     }
174     Uint8Buff messageBufSelf = { messageSelf, length };
175     Uint8Buff pskBuf = { (uint8_t *)params->psk, sizeof(params->psk) };
176     KeyParams keyParams = { { pskBuf.val, pskBuf.length, false }, false, params->osAccountId };
177     res = params->loader->computeHmac(&keyParams, &messageBufSelf, selfToken);
178     if (res != HC_SUCCESS) {
179         LOGE("ComputeHmac for selfToken failed, res: %x.", res);
180         goto CLEAN_UP;
181     }
182 CLEAN_UP:
183     HcFree(messageSelf);
184     return res;
185 }
186 
IsoCombineHkdfSalt(IsoBaseParams * params,Uint8Buff * hkdfSaltBuf,bool isClient)187 static int IsoCombineHkdfSalt(IsoBaseParams *params, Uint8Buff *hkdfSaltBuf, bool isClient)
188 {
189     if (isClient) {
190         if (memcpy_s(hkdfSaltBuf->val, hkdfSaltBuf->length, params->randSelf.val, params->randSelf.length) != EOK) {
191             LOGE("Memcpy randSelf failed.");
192             return HC_ERR_MEMORY_COPY;
193         }
194         if (memcpy_s(hkdfSaltBuf->val + params->randSelf.length, hkdfSaltBuf->length - params->randSelf.length,
195             params->randPeer.val, params->randPeer.length) != EOK) {
196             LOGE("Memcpy randPeer failed.");
197             return HC_ERR_MEMORY_COPY;
198         }
199     } else {
200         if (memcpy_s(hkdfSaltBuf->val, hkdfSaltBuf->length, params->randPeer.val, params->randPeer.length) != EOK) {
201             LOGE("Memcpy randPeer failed.");
202             return HC_ERR_MEMORY_COPY;
203         }
204         if (memcpy_s(hkdfSaltBuf->val + params->randPeer.length, hkdfSaltBuf->length - params->randPeer.length,
205             params->randSelf.val, params->randSelf.length) != EOK) {
206             LOGE("Memcpy randSelf failed.");
207             return HC_ERR_MEMORY_COPY;
208         }
209     }
210     return HC_SUCCESS;
211 }
212 
IsoGenSessionKey(IsoBaseParams * params,Uint8Buff * pskBuf,bool isClient)213 static int IsoGenSessionKey(IsoBaseParams *params, Uint8Buff *pskBuf, bool isClient)
214 {
215     uint32_t hkdfSaltLen = params->randPeer.length + params->randSelf.length;
216     uint8_t *hkdfSalt = (uint8_t *)HcMalloc(hkdfSaltLen, 0);
217     if (hkdfSalt == NULL) {
218         LOGE("Malloc for hkdfSalt failed.");
219         return HC_ERR_ALLOC_MEMORY;
220     }
221     Uint8Buff hkdfSaltBuf = { hkdfSalt, hkdfSaltLen };
222     int res = IsoCombineHkdfSalt(params, &hkdfSaltBuf, isClient);
223     if (res != HC_SUCCESS) {
224         LOGE("IsoCombineHkdfSalt failed, res: %x.", res);
225         HcFree(hkdfSalt);
226         return res;
227     }
228 
229     Uint8Buff keyInfoBuf = { (uint8_t *)GENERATE_SESSION_KEY_STR, HcStrlen(GENERATE_SESSION_KEY_STR) };
230     KeyParams keyParams = { { pskBuf->val, pskBuf->length, false }, false, params->osAccountId };
231     res = params->loader->computeHkdf(&keyParams, &hkdfSaltBuf, &keyInfoBuf, &params->sessionKey);
232     if (res != HC_SUCCESS) {
233         LOGE("ComputeHkdf for sessionKey failed, res: %x.", res);
234         FreeAndCleanKey(&params->sessionKey);
235     }
236     HcFree(hkdfSalt);
237     return res;
238 }
239 
IsoClientGenRandom(IsoBaseParams * params)240 int IsoClientGenRandom(IsoBaseParams *params)
241 {
242     if (params == NULL) {
243         LOGE("Params is null.");
244         return HC_ERR_NULL_PTR;
245     }
246     int32_t res = params->loader->generateRandom(&params->randSelf);
247     if (res != HC_SUCCESS) {
248         LOGE("Generate randSelf failed, res: %x.", res);
249         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
250     }
251     return res;
252 }
253 
IsoClientCheckAndGenToken(IsoBaseParams * params,const Uint8Buff * peerToken,Uint8Buff * selfToken)254 int IsoClientCheckAndGenToken(IsoBaseParams *params, const Uint8Buff *peerToken, Uint8Buff *selfToken)
255 {
256     if (params == NULL) {
257         LOGE("Params is null.");
258         return HC_ERR_NULL_PTR;
259     }
260     if (peerToken == NULL || selfToken == NULL) {
261         LOGE("Params is null.");
262         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
263         return HC_ERR_NULL_PTR;
264     }
265 
266     uint8_t hmacPeer[SHA256_LEN] = { 0 };
267     Uint8Buff outHmac = { hmacPeer, sizeof(hmacPeer) };
268     int res = IsoCalSelfToken(params, &outHmac);
269     if (res != HC_SUCCESS) {
270         LOGE("IsoCalSelfToken failed, res: %x.", res);
271         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
272         return res;
273     }
274     if (memcmp(peerToken->val, outHmac.val, outHmac.length) != 0) {
275         LOGE("Compare hmac token failed.");
276         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
277         return PROOF_MISMATCH;
278     }
279     res = IsoCalPeerToken(params, selfToken);
280     if (res != HC_SUCCESS) {
281         LOGE("IsoCalPeerToken failed, res: %x.", res);
282         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
283     }
284     return res;
285 }
286 
IsoClientGenSessionKey(IsoBaseParams * params,int returnResult,const uint8_t * hmac,uint32_t hmacLen)287 int IsoClientGenSessionKey(IsoBaseParams *params, int returnResult, const uint8_t *hmac, uint32_t hmacLen)
288 {
289     if (params == NULL) {
290         LOGE("Params is null.");
291         return HC_ERR_NULL_PTR;
292     }
293     if (hmac == NULL) {
294         LOGE("Params is null.");
295         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
296         return HC_ERR_NULL_PTR;
297     }
298 
299     Uint8Buff pskBuf = { params->psk, sizeof(params->psk) };
300     Uint8Buff hmacMessage = { (uint8_t *)&returnResult, sizeof(int) };
301     uint8_t hmacSelf[SHA256_LEN] = { 0 };
302     Uint8Buff outHmacBuf = { hmacSelf, sizeof(hmacSelf) };
303     KeyParams keyParams = { { pskBuf.val, pskBuf.length, false }, false, params->osAccountId };
304     int res = params->loader->computeHmac(&keyParams, &hmacMessage, &outHmacBuf);
305     if (res != HC_SUCCESS) {
306         LOGE("ComputeHmac for returnResult failed, res: %x.", res);
307         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
308         return res;
309     }
310     if (memcmp(outHmacBuf.val, hmac, hmacLen) != 0) {
311         LOGE("Compare hmac result failed.");
312         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
313         return PROOF_MISMATCH;
314     }
315 
316     res = IsoGenSessionKey(params, &pskBuf, true);
317     if (res != HC_SUCCESS) {
318         LOGE("IsoGenSessionKey failed, res: %x.", res);
319         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
320     }
321 
322     return res;
323 }
324 
IsoServerGenRandomAndToken(IsoBaseParams * params,Uint8Buff * selfTokenBuf)325 int IsoServerGenRandomAndToken(IsoBaseParams *params, Uint8Buff *selfTokenBuf)
326 {
327     if (params == NULL) {
328         LOGE("Params is null.");
329         return HC_ERR_NULL_PTR;
330     }
331     if (selfTokenBuf == NULL) {
332         LOGE("Params is null.");
333         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
334         return HC_ERR_NULL_PTR;
335     }
336     int res = params->loader->generateRandom(&params->randSelf);
337     if (res != HC_SUCCESS) {
338         LOGE("Generate randSelf failed, res: %x.", res);
339         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
340         return res;
341     }
342     res = IsoCalPeerToken(params, selfTokenBuf);
343     if (res != HC_SUCCESS) {
344         LOGE("IsoCalPeerToken failed, res: %x.", res);
345         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
346     }
347     return res;
348 }
349 
IsoServerGenSessionKeyAndCalToken(IsoBaseParams * params,const Uint8Buff * tokenFromPeer,Uint8Buff * tokenToPeer)350 int IsoServerGenSessionKeyAndCalToken(IsoBaseParams *params, const Uint8Buff *tokenFromPeer, Uint8Buff *tokenToPeer)
351 {
352     if (params == NULL) {
353         LOGE("Params is null.");
354         return HC_ERR_NULL_PTR;
355     }
356     if (tokenFromPeer == NULL || tokenToPeer == NULL) {
357         LOGE("Params is null.");
358         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
359         return HC_ERR_NULL_PTR;
360     }
361 
362     uint8_t hmacPeer[SHA256_LEN] = { 0 };
363     Uint8Buff outHmac = { hmacPeer, sizeof(hmacPeer) };
364     int res = IsoCalSelfToken(params, &outHmac);
365     if (res != HC_SUCCESS) {
366         LOGE("IsoCalSelfToken failed, res: %x.", res);
367         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
368         return res;
369     }
370     if (memcmp(tokenFromPeer->val, outHmac.val, outHmac.length) != 0) {
371         LOGE("Compare hmac token failed.");
372         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
373         return PROOF_MISMATCH;
374     }
375 
376     Uint8Buff pskBuf = { params->psk, sizeof(params->psk) };
377     res = IsoGenSessionKey(params, &pskBuf, false);
378     if (res != HC_SUCCESS) {
379         LOGE("IsoGenSessionKey failed, res: %x.", res);
380         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
381         return res;
382     }
383 
384     int returnCode = 0;
385     Uint8Buff messageBuf = { (uint8_t *)&returnCode, sizeof(int) };
386     KeyParams keyParams = { { pskBuf.val, pskBuf.length, false }, false, params->osAccountId };
387     res = params->loader->computeHmac(&keyParams, &messageBuf, tokenToPeer);
388     if (res != HC_SUCCESS) {
389         LOGE("Compute hmac for returnCode failed, res: %x.", res);
390         (void)memset_s(params->psk, sizeof(params->psk), 0, PSK_LEN);
391         FreeAndCleanKey(&params->sessionKey);
392     }
393     return res;
394 }