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 }