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, ¶ms->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(¶ms->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, ¶ms->sessionKey);
232 if (res != HC_SUCCESS) {
233 LOGE("ComputeHkdf for sessionKey failed, res: %x.", res);
234 FreeAndCleanKey(¶ms->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(¶ms->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(¶ms->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(¶ms->sessionKey);
392 }
393 return res;
394 }