1 /*
2 * Copyright (C) 2023 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 "key_manager.h"
17
18 #include "alg_defs.h"
19 #include "alg_loader.h"
20 #include "common_defs.h"
21 #include "device_auth_defines.h"
22 #include "hc_dev_info.h"
23 #include "hc_log.h"
24 #include "hc_types.h"
25 #include "json_utils.h"
26 #include "pseudonym_manager.h"
27 #include "uint8buff_utils.h"
28
29 #define PAKE_X25519_KEY_PAIR_LEN 32
30 #define MK_LEN 32
31 #define MK_DERIVE_INFO "dev_auth_mk_derivation"
32 #define PAKE_KEY_ALIAS_LEN 64
33 #define MK_ALIAS_PREFIX "MK_"
34 #define PSEUDONYM_PSK_ALIAS_PREFIX "PSEUDONYM_"
35
ConvertHashToAlias(const Uint8Buff * keyAliasHash,Uint8Buff * outKeyAlias)36 static int32_t ConvertHashToAlias(const Uint8Buff *keyAliasHash, Uint8Buff *outKeyAlias)
37 {
38 uint32_t keyAliasHexLen = keyAliasHash->length * BYTE_TO_HEX_OPER_LENGTH + 1;
39 char *keyAliasHex = (char *)HcMalloc(keyAliasHexLen, 0);
40 if (keyAliasHex == NULL) {
41 LOGE("Failed to alloc key alias hex memory!");
42 return HC_ERR_ALLOC_MEMORY;
43 }
44 int32_t res = ByteToHexString(keyAliasHash->val, keyAliasHash->length, keyAliasHex, keyAliasHexLen);
45 if (res != HC_SUCCESS) {
46 LOGE("Failed to convert key alias hash to hex!");
47 HcFree(keyAliasHex);
48 return res;
49 }
50 if (memcpy_s(outKeyAlias->val, outKeyAlias->length, keyAliasHex, HcStrlen(keyAliasHex)) != EOK) {
51 LOGE("Failed to copy key alias hex!");
52 HcFree(keyAliasHex);
53 return HC_ERR_MEMORY_COPY;
54 }
55 HcFree(keyAliasHex);
56 return HC_SUCCESS;
57 }
58
ConvertHashToAliasWithPrefix(const char * prefix,const Uint8Buff * keyAliasHash,Uint8Buff * keyAlias)59 static int32_t ConvertHashToAliasWithPrefix(const char *prefix, const Uint8Buff *keyAliasHash, Uint8Buff *keyAlias)
60 {
61 uint32_t keyAliasHexLen = keyAliasHash->length * BYTE_TO_HEX_OPER_LENGTH + 1;
62 char *keyAliasHex = (char *)HcMalloc(keyAliasHexLen, 0);
63 if (keyAliasHex == NULL) {
64 LOGE("Failed to alloc key alias hex memory!");
65 return HC_ERR_ALLOC_MEMORY;
66 }
67 int32_t res = ByteToHexString(keyAliasHash->val, keyAliasHash->length, keyAliasHex, keyAliasHexLen);
68 if (res != HC_SUCCESS) {
69 LOGE("Failed to convert key alias hash to hex!");
70 HcFree(keyAliasHex);
71 return res;
72 }
73 uint32_t prefixLen = HcStrlen(prefix);
74 if (memcpy_s(keyAlias->val, keyAlias->length, prefix, prefixLen) != EOK) {
75 LOGE("Failed to copy key alias prefix!");
76 HcFree(keyAliasHex);
77 return HC_ERR_MEMORY_COPY;
78 }
79 // The remaining key alias len is less than keyAliasHexLen len after substract prefixLen,
80 // so copy the remaining len other than keyAliasHexLen in order that the key alias len is 64.
81 if (memcpy_s(keyAlias->val + prefixLen, keyAlias->length - prefixLen, keyAliasHex,
82 keyAlias->length - prefixLen) != EOK) {
83 LOGE("Failed to copy key alias hex!");
84 HcFree(keyAliasHex);
85 return HC_ERR_MEMORY_COPY;
86 }
87 HcFree(keyAliasHex);
88 return HC_SUCCESS;
89 }
90
GenerateDevKeyAlias(Uint8Buff * outKeyAlias)91 static int32_t GenerateDevKeyAlias(Uint8Buff *outKeyAlias)
92 {
93 char selfUdid[INPUT_UDID_LEN] = { 0 };
94 int32_t res = HcGetUdid((uint8_t *)selfUdid, INPUT_UDID_LEN);
95 if (res != HC_SUCCESS) {
96 LOGE("Failed to get local udid!");
97 return res;
98 }
99 uint8_t hashValue[SHA256_LEN] = { 0 };
100 Uint8Buff keyAliasHash = { hashValue, SHA256_LEN };
101 Uint8Buff msgBuff = { (uint8_t *)selfUdid, HcStrlen(selfUdid) };
102 res = GetLoaderInstance()->sha256(&msgBuff, &keyAliasHash);
103 if (res != HC_SUCCESS) {
104 LOGE("Failed to generate key alias hash!");
105 return res;
106 }
107 res = ConvertHashToAlias(&keyAliasHash, outKeyAlias);
108 if (res != HC_SUCCESS) {
109 LOGE("Failed to convert hash to alias!");
110 }
111 return res;
112 }
113
GenerateMkAlias(const char * peerDeviceId,Uint8Buff * keyAlias)114 static int32_t GenerateMkAlias(const char *peerDeviceId, Uint8Buff *keyAlias)
115 {
116 Uint8Buff peerDevIdBuff = { (uint8_t *)peerDeviceId, HcStrlen(peerDeviceId) };
117 uint8_t hashValue[SHA256_LEN] = { 0 };
118 Uint8Buff keyAliasHash = { hashValue, SHA256_LEN };
119 int32_t res = GetLoaderInstance()->sha256(&peerDevIdBuff, &keyAliasHash);
120 if (res != HC_SUCCESS) {
121 LOGE("Failed to generate key alias hash!");
122 return res;
123 }
124 res = ConvertHashToAliasWithPrefix(MK_ALIAS_PREFIX, &keyAliasHash, keyAlias);
125 if (res != HC_SUCCESS) {
126 LOGE("Failed to convert hash to alias!");
127 }
128 return res;
129 }
130
GeneratePseudonymPskAlias(const char * peerDeviceId,Uint8Buff * keyAlias)131 static int32_t GeneratePseudonymPskAlias(const char *peerDeviceId, Uint8Buff *keyAlias)
132 {
133 uint8_t hashValue[SHA256_LEN] = { 0 };
134 Uint8Buff keyAliasHash = { hashValue, SHA256_LEN };
135 Uint8Buff peerDevIdBuff = { (uint8_t *)peerDeviceId, HcStrlen(peerDeviceId) };
136 int32_t res = GetLoaderInstance()->sha256(&peerDevIdBuff, &keyAliasHash);
137 if (res != HC_SUCCESS) {
138 LOGE("Failed to generate key alias hash!");
139 return res;
140 }
141
142 res = ConvertHashToAliasWithPrefix(PSEUDONYM_PSK_ALIAS_PREFIX, &keyAliasHash, keyAlias);
143 if (res != HC_SUCCESS) {
144 LOGE("Failed to convert hash to alias!");
145 }
146 return res;
147 }
148
KeyDerivation(int32_t osAccountId,const Uint8Buff * baseAlias,const Uint8Buff * salt,bool isAlias,Uint8Buff * returnKey)149 static int32_t KeyDerivation(int32_t osAccountId, const Uint8Buff *baseAlias, const Uint8Buff *salt, bool isAlias,
150 Uint8Buff *returnKey)
151 {
152 Uint8Buff keyInfo = { (uint8_t *)MK_DERIVE_INFO, HcStrlen(MK_DERIVE_INFO) };
153 KeyParams keyAliasParams = { { baseAlias->val, baseAlias->length, isAlias }, false, osAccountId };
154 int32_t res = GetLoaderInstance()->computeHkdf(&keyAliasParams, salt, &keyInfo, returnKey);
155 if (res != HC_SUCCESS) {
156 LOGE("Failed to compute hkdf!");
157 }
158 return res;
159 }
160
GenerateDeviceKeyPair(int32_t osAccountId)161 int32_t GenerateDeviceKeyPair(int32_t osAccountId)
162 {
163 uint8_t keyAlias[PAKE_KEY_ALIAS_LEN] = { 0 };
164 Uint8Buff keyAliasBuff = { keyAlias, PAKE_KEY_ALIAS_LEN };
165 int32_t res = GenerateDevKeyAlias(&keyAliasBuff);
166 if (res != HC_SUCCESS) {
167 LOGE("Failed to generate device key alias!");
168 return res;
169 }
170 if (GetLoaderInstance()->checkKeyExist(&keyAliasBuff, false, osAccountId) == HC_SUCCESS) {
171 LOGI("Device Key pair already exists!");
172 return HC_SUCCESS;
173 }
174
175 char selfUdid[INPUT_UDID_LEN] = { 0 };
176 res = HcGetUdid((uint8_t *)selfUdid, INPUT_UDID_LEN);
177 if (res != HC_SUCCESS) {
178 LOGE("Failed to get local udid!");
179 return res;
180 }
181 Uint8Buff authIdBuff = { (uint8_t *)selfUdid, HcStrlen(selfUdid) };
182 ExtraInfo exInfo = { authIdBuff, -1, -1 };
183 KeyParams keyParams = { { keyAliasBuff.val, keyAliasBuff.length, true }, false, osAccountId };
184 res = GetLoaderInstance()->generateKeyPairWithStorage(&keyParams, PAKE_X25519_KEY_PAIR_LEN, X25519,
185 KEY_PURPOSE_SIGN_VERIFY, &exInfo);
186 if (res != HC_SUCCESS) {
187 LOGE("Failed to generate device key pair!");
188 return res;
189 }
190 LOGI("Generate device key pair successfully!");
191 return HC_SUCCESS;
192 }
193
GenerateMk(int32_t osAccountId,const char * peerDeviceId,const Uint8Buff * peerPubKey)194 int32_t GenerateMk(int32_t osAccountId, const char *peerDeviceId, const Uint8Buff *peerPubKey)
195 {
196 if (peerDeviceId == NULL || peerPubKey == NULL) {
197 LOGE("Invalid input params!");
198 return HC_ERR_INVALID_PARAMS;
199 }
200 uint8_t mkAlias[PAKE_KEY_ALIAS_LEN] = { 0 };
201 Uint8Buff mkAliasBuff = { mkAlias, PAKE_KEY_ALIAS_LEN };
202 int32_t res = GenerateMkAlias(peerDeviceId, &mkAliasBuff);
203 if (res != HC_SUCCESS) {
204 LOGE("Failed to generate mk alias!");
205 return res;
206 }
207 uint8_t devKeyAlias[PAKE_KEY_ALIAS_LEN] = { 0 };
208 Uint8Buff devKeyAliasBuff = { devKeyAlias, PAKE_KEY_ALIAS_LEN };
209 res = GenerateDevKeyAlias(&devKeyAliasBuff);
210 if (res != HC_SUCCESS) {
211 LOGE("Failed to generate device key alias!");
212 return res;
213 }
214 KeyParams selfKeyParams = { { devKeyAliasBuff.val, devKeyAliasBuff.length, true }, false, osAccountId };
215 KeyBuff peerKeyBuff = { peerPubKey->val, peerPubKey->length, false };
216 res = GetLoaderInstance()->agreeSharedSecretWithStorage(&selfKeyParams, &peerKeyBuff, X25519,
217 MK_LEN, &mkAliasBuff);
218 if (res != HC_SUCCESS) {
219 LOGE("Failed to agree sharedSecret!");
220 return res;
221 }
222 LOGI("Generate mk successfully!");
223 return HC_SUCCESS;
224 }
225
DeleteMk(int32_t osAccountId,const char * peerDeviceId)226 int32_t DeleteMk(int32_t osAccountId, const char *peerDeviceId)
227 {
228 if (peerDeviceId == NULL) {
229 LOGE("Invalid input param!");
230 return HC_ERR_INVALID_PARAMS;
231 }
232 uint8_t mkAlias[PAKE_KEY_ALIAS_LEN] = { 0 };
233 Uint8Buff mkAliasBuff = { mkAlias, PAKE_KEY_ALIAS_LEN };
234 int32_t res = GenerateMkAlias(peerDeviceId, &mkAliasBuff);
235 if (res != HC_SUCCESS) {
236 LOGE("Failed to generate mk alias!");
237 return res;
238 }
239 if (GetLoaderInstance()->checkKeyExist(&mkAliasBuff, false, osAccountId) != HC_SUCCESS) {
240 LOGI("mk does not exist, no need to delete!");
241 return HC_SUCCESS;
242 }
243 res = GetLoaderInstance()->deleteKey(&mkAliasBuff, false, osAccountId);
244 if (res != HC_SUCCESS) {
245 LOGE("Failed to delete mk!");
246 return res;
247 }
248 LOGI("Delete mk successfully!");
249 return HC_SUCCESS;
250 }
251
GeneratePseudonymPsk(int32_t osAccountId,const char * peerDeviceId,const Uint8Buff * salt)252 int32_t GeneratePseudonymPsk(int32_t osAccountId, const char *peerDeviceId, const Uint8Buff *salt)
253 {
254 if (peerDeviceId == NULL || salt == NULL) {
255 LOGE("Invalid input params!");
256 return HC_ERR_INVALID_PARAMS;
257 }
258 uint8_t pseudonymPskAlias[PAKE_KEY_ALIAS_LEN] = { 0 };
259 Uint8Buff pskAliasBuff = { pseudonymPskAlias, PAKE_KEY_ALIAS_LEN };
260 int32_t res = GeneratePseudonymPskAlias(peerDeviceId, &pskAliasBuff);
261 if (res != HC_SUCCESS) {
262 LOGE("Failed to generate pseudonym psk alias!");
263 return res;
264 }
265 uint8_t mkAlias[PAKE_KEY_ALIAS_LEN] = { 0 };
266 Uint8Buff mkAliasBuff = { mkAlias, PAKE_KEY_ALIAS_LEN };
267 res = GenerateMkAlias(peerDeviceId, &mkAliasBuff);
268 if (res != HC_SUCCESS) {
269 LOGE("Failed to generate mk alias!");
270 return res;
271 }
272 Uint8Buff pskBuff = { NULL, 0 };
273 if (InitUint8Buff(&pskBuff, MK_LEN) != HC_SUCCESS) {
274 LOGE("Failed to init pseudonym psk!");
275 return HC_ERR_ALLOC_MEMORY;
276 }
277 res = KeyDerivation(osAccountId, &mkAliasBuff, salt, true, &pskBuff);
278 if (res != HC_SUCCESS) {
279 LOGE("Failed to derive pseudonym psk!");
280 FreeUint8Buff(&pskBuff);
281 return res;
282 }
283 KeyParams keyParams = { { pskAliasBuff.val, pskAliasBuff.length, true }, false, osAccountId };
284 res = GetLoaderInstance()->importSymmetricKey(&keyParams, &pskBuff, KEY_PURPOSE_MAC, NULL);
285 ClearFreeUint8Buff(&pskBuff);
286 if (res != HC_SUCCESS) {
287 LOGE("Failed to import pseudonym psk!");
288 return res;
289 }
290 LOGI("Generate and save pseudonym psk successfully!");
291 return HC_SUCCESS;
292 }
293
DeletePseudonymPsk(int32_t osAccountId,const char * peerDeviceId)294 int32_t DeletePseudonymPsk(int32_t osAccountId, const char *peerDeviceId)
295 {
296 if (peerDeviceId == NULL) {
297 LOGE("Invalid input param!");
298 return HC_ERR_INVALID_PARAMS;
299 }
300 uint8_t pseudonymPskAlias[PAKE_KEY_ALIAS_LEN] = { 0 };
301 Uint8Buff pskAliasBuff = { pseudonymPskAlias, PAKE_KEY_ALIAS_LEN };
302 int32_t res = GeneratePseudonymPskAlias(peerDeviceId, &pskAliasBuff);
303 if (res != HC_SUCCESS) {
304 LOGE("Failed to generate psk alias!");
305 return res;
306 }
307 if (GetLoaderInstance()->checkKeyExist(&pskAliasBuff, false, osAccountId) != HC_SUCCESS) {
308 LOGI("Pseudonym psk does not exist, no need to delete!");
309 return HC_SUCCESS;
310 }
311 res = GetLoaderInstance()->deleteKey(&pskAliasBuff, false, osAccountId);
312 if (res != HC_SUCCESS) {
313 LOGE("Failed to delete pseudonym psk!");
314 return res;
315 }
316 LOGI("Delete pseudonym psk successfully!");
317 return HC_SUCCESS;
318 }
319
GenerateAndSavePseudonymId(int32_t osAccountId,const char * peerDeviceId,const PseudonymKeyInfo * info,const Uint8Buff * saltBuff,Uint8Buff * returnHmac)320 int32_t GenerateAndSavePseudonymId(int32_t osAccountId, const char *peerDeviceId, const PseudonymKeyInfo *info,
321 const Uint8Buff *saltBuff, Uint8Buff *returnHmac)
322 {
323 if (peerDeviceId == NULL || info == NULL || saltBuff == NULL || returnHmac == NULL) {
324 LOGE("Invalid input params!");
325 return HC_ERR_INVALID_PARAMS;
326 }
327 uint8_t pskAliasVal[PAKE_KEY_ALIAS_LEN] = { 0 };
328 Uint8Buff pskAliasBuff = { pskAliasVal, PAKE_KEY_ALIAS_LEN };
329 int32_t res = GeneratePseudonymPskAlias(peerDeviceId, &pskAliasBuff);
330 if (res != HC_SUCCESS) {
331 LOGE("Failed to generate pseudonym psk alias!");
332 return res;
333 }
334 uint8_t pseudonymIdVal[MK_LEN] = { 0 };
335 Uint8Buff pseudonymIdBuff = { pseudonymIdVal, MK_LEN };
336 KeyParams keyParams = { { pskAliasBuff.val, pskAliasBuff.length, true }, false, osAccountId };
337 res = GetLoaderInstance()->computeHmac(&keyParams, saltBuff, &pseudonymIdBuff);
338 if (res != HC_SUCCESS) {
339 LOGE("Failed to compute hmac!");
340 return res;
341 }
342 if (DeepCopyUint8Buff(&pseudonymIdBuff, returnHmac) != HC_SUCCESS) {
343 LOGE("Failed to copy hmac!");
344 return HC_ERR_ALLOC_MEMORY;
345 }
346 uint32_t pdidLen = pseudonymIdBuff.length * BYTE_TO_HEX_OPER_LENGTH + 1;
347 char *pdid = (char *)HcMalloc(pdidLen, 0);
348 if (pdid == NULL) {
349 LOGE("Failed to alloc memory for pdid!");
350 ClearFreeUint8Buff(returnHmac);
351 return HC_ERR_ALLOC_MEMORY;
352 }
353 res = ByteToHexString(pseudonymIdBuff.val, pseudonymIdBuff.length, pdid, pdidLen);
354 if (res != HC_SUCCESS) {
355 LOGE("Failed to convert pdid from byte to hex string!");
356 ClearFreeUint8Buff(returnHmac);
357 HcFree(pdid);
358 return res;
359 }
360 res = GetPseudonymInstance()->savePseudonymId(osAccountId, pdid, info->peerInfo, peerDeviceId, info->pdidIndex);
361 HcFree(pdid);
362 if (res != HC_SUCCESS) {
363 LOGE("Failed to save pdid!");
364 ClearFreeUint8Buff(returnHmac);
365 return res;
366 }
367 LOGI("Generate and save pdid successfully!");
368 return HC_SUCCESS;
369 }
370
GetDevicePubKey(int32_t osAccountId,Uint8Buff * devicePk)371 int32_t GetDevicePubKey(int32_t osAccountId, Uint8Buff *devicePk)
372 {
373 if (devicePk == NULL) {
374 LOGE("Invalid input param!");
375 return HC_ERR_INVALID_PARAMS;
376 }
377 uint8_t keyAlias[PAKE_KEY_ALIAS_LEN] = { 0 };
378 Uint8Buff keyAliasBuff = { keyAlias, PAKE_KEY_ALIAS_LEN };
379 int32_t res = GenerateDevKeyAlias(&keyAliasBuff);
380 if (res != HC_SUCCESS) {
381 LOGE("Failed to generate device key alias!");
382 return res;
383 }
384 KeyParams keyParams = { { keyAliasBuff.val, keyAliasBuff.length, true }, false, osAccountId };
385 res = GetLoaderInstance()->exportPublicKey(&keyParams, devicePk);
386 if (res != HC_SUCCESS) {
387 LOGE("Failed to export device pk!");
388 }
389 return res;
390 }