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