1 /*
2  * Copyright (c) 2020-2024 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 "hks_rkc_v1.h"
17 
18 #include "hks_crypto_hal.h"
19 #include "hks_get_process_info.h"
20 #include "hks_get_udid.h"
21 #include "hks_log.h"
22 #include "hks_mem.h"
23 #include "hks_param.h"
24 #include "hks_rkc.h"
25 #include "hks_storage_manager.h"
26 #include "hks_template.h"
27 
RkcExtractKsfBufV1(const struct HksBlob * ksfFromFile,struct HksRkcKsfDataV1 * ksfData)28 static int32_t RkcExtractKsfBufV1(const struct HksBlob *ksfFromFile, struct HksRkcKsfDataV1 *ksfData)
29 {
30     uint32_t ksfBufOffset = 0;
31 
32     /* Extract file flag. */
33     int32_t ret = RkcExtractKsfFileFlag(ksfFromFile, &ksfBufOffset);
34     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Rkc extract ksf flag failed! ret = 0x%" LOG_PUBLIC "X", ret)
35 
36      /* Extract version */
37     ret = ExtractFieldFromBuffer(ksfFromFile, &ksfBufOffset, &(ksfData->version), sizeof(ksfData->version));
38     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Rkc extract ksf version failed! ret = 0x%" LOG_PUBLIC "X", ret)
39 
40     /* Extract root key data */
41     ret = ExtractKsfDataRkc(ksfFromFile, &ksfBufOffset, &(ksfData->ksfDataRkc));
42     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Rkc extract ksf rk failed! ret = 0x%" LOG_PUBLIC "X", ret)
43 
44     /* Extract fields of main key */
45     ret = ExtractKsfDataMk(ksfFromFile, &ksfBufOffset, &(ksfData->ksfDataMk));
46     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Rkc extract ksf mk failed! ret = 0x%" LOG_PUBLIC "X", ret)
47 
48     /* Extract hash */
49     return RkcExtractKsfHash(ksfFromFile, &ksfBufOffset);
50 }
51 
HksRkcReadKsfV1(const char * ksfName,struct HksRkcKsfDataV1 * ksfData)52 static int32_t HksRkcReadKsfV1(const char *ksfName, struct HksRkcKsfDataV1 *ksfData)
53 {
54     if (ksfName == NULL) {
55         return HKS_ERROR_NULL_POINTER;
56     }
57 
58     struct HksBlob tmpKsf;
59     int32_t ret = GetKeyBlobKsf(ksfName, &tmpKsf);
60     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Get ksf file failed! ret = 0x%" LOG_PUBLIC "X", ret)
61 
62     ret = RkcExtractKsfBufV1(&tmpKsf, ksfData);
63 
64     /* the data of root key should be cleared after use */
65     (void)memset_s(tmpKsf.data, tmpKsf.size, 0, tmpKsf.size);
66     HKS_FREE_BLOB(tmpKsf);
67     return ret;
68 }
69 
RkcReadAllKsfV1(struct HksRkcKsfDataV1 * validKsfData)70 static int32_t RkcReadAllKsfV1(struct HksRkcKsfDataV1 *validKsfData)
71 {
72     /* Read all rkc ksf */
73     int32_t readRet[HKS_KSF_NUM] = { 0 };
74     struct HksRkcKsfDataV1 allRkcData[HKS_KSF_NUM] = { { 0 } };
75     for (uint32_t i = 0; i < HKS_KSF_NUM; ++i) {
76         readRet[i] = HksRkcReadKsfV1(GetGlobalKsfAttrRkc()->name[i], &(allRkcData[i]));
77     }
78 
79     int32_t validIndex = 0;
80     for (; validIndex < HKS_KSF_NUM; validIndex++) {
81         if (readRet[validIndex] == HKS_SUCCESS) {
82             break;
83         }
84     }
85     if (validIndex == HKS_KSF_NUM) {
86         return HKS_ERROR_INVALID_KEY_FILE;
87     }
88 
89     // version 1: no need to rewrite for recovery
90     (void)memcpy_s(validKsfData, sizeof(struct HksRkcKsfDataV1),
91         &allRkcData[validIndex], sizeof(struct HksRkcKsfDataV1));
92     return HKS_SUCCESS;
93 }
94 
RkcGetFixedMaterialV1(struct HksBlob * material)95 static int32_t RkcGetFixedMaterialV1(struct HksBlob *material)
96 {
97     /* consistent with the old hks */
98     const uint8_t fixedMaterial[HKS_RKC_MATERIAL_LEN] = {
99         0xB2, 0xA1, 0x0C, 0x73, 0x52, 0x73, 0x76, 0xA1,
100         0x60, 0x62, 0x2E, 0x08, 0x52, 0x08, 0x2E, 0xA9,
101         0x60, 0xBC, 0x2E, 0x73, 0x52, 0x0B, 0x0C, 0xBC,
102         0xEE, 0x0A, 0x2E, 0x08, 0x52, 0x9C, 0x76, 0xA9
103     };
104 
105     if (memcpy_s(material->data, material->size, fixedMaterial, HKS_RKC_MATERIAL_LEN) != EOK) {
106         HKS_LOG_E("Memcpy fiexd material failed!");
107         return HKS_ERROR_INSUFFICIENT_MEMORY;
108     }
109 
110     return HKS_SUCCESS;
111 }
112 
RkcGetRmkRawKeyV1(const struct HksKsfDataRkc * ksfDataRkc,struct HksBlob * rawKey)113 static int32_t RkcGetRmkRawKeyV1(const struct HksKsfDataRkc *ksfDataRkc, struct HksBlob *rawKey)
114 {
115     uint8_t material3Data[HKS_RKC_MATERIAL_LEN] = {0};
116     struct HksBlob material3 = { HKS_RKC_MATERIAL_LEN, material3Data };
117 
118     /* Get the fixed material */
119     int32_t ret = RkcGetFixedMaterialV1(&material3);
120     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Get fixed material failed! ret = 0x%" LOG_PUBLIC "X", ret)
121 
122     /* materials xor */
123     for (uint32_t i = 0; i < HKS_RKC_MATERIAL_LEN; ++i) {
124         rawKey->data[i] = ksfDataRkc->rkMaterial1[i] ^ ksfDataRkc->rkMaterial2[i] ^ material3.data[i];
125     }
126 
127     /* append hardware UDID */
128     ret = HksGetHardwareUdid(rawKey->data + HKS_RKC_MATERIAL_LEN, HKS_HARDWARE_UDID_LEN);
129     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Get hardware udid failed! ret = 0x%" LOG_PUBLIC "X", ret)
130 
131     return HKS_SUCCESS;
132 }
133 
RkcPbkdf2Hmac(const uint32_t hashAlg,const struct HksBlob * rawKey,const struct HksBlob * salt,const uint32_t iterNum,struct HksBlob * dk)134 static int32_t RkcPbkdf2Hmac(const uint32_t hashAlg, const struct HksBlob *rawKey,
135     const struct HksBlob *salt, const uint32_t iterNum, struct HksBlob *dk)
136 {
137     struct HksKeyDerivationParam derParam = {
138         .salt = *salt,
139         .iterations = iterNum,
140         .digestAlg = RkcDigestToHks(hashAlg),
141     };
142     const struct HksKeySpec derivationSpec = { HKS_ALG_PBKDF2, dk->size, &derParam };
143     int32_t ret = HksCryptoHalDeriveKey(rawKey, &derivationSpec, dk);
144     HKS_IF_NOT_SUCC_LOGE(ret, "Crypto hal derive key failed! ret = 0x%" LOG_PUBLIC "X", ret)
145 
146     return ret;
147 }
148 
RkcDeriveRmkV1(const struct HksKsfDataRkc * ksfDataRkc,struct HksBlob * rmk)149 static int32_t RkcDeriveRmkV1(const struct HksKsfDataRkc *ksfDataRkc, struct HksBlob *rmk)
150 {
151     struct HksBlob rawKey;
152     rawKey.data = (uint8_t *)HksMalloc(HKS_RKC_RAW_KEY_LEN);
153     HKS_IF_NULL_LOGE_RETURN(rawKey.data, HKS_ERROR_MALLOC_FAIL, "Malloc rawKey failed!")
154 
155     rawKey.size = HKS_RKC_RAW_KEY_LEN;
156     (void)memset_s(rawKey.data, rawKey.size, 0, rawKey.size);
157 
158     int32_t ret;
159     do {
160         /* get the raw key */
161         ret = RkcGetRmkRawKeyV1(ksfDataRkc, &rawKey);
162         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "Get rmk raw key failed! ret = 0x%" LOG_PUBLIC "X", ret)
163 
164         /* PBKDF2-HMAC */
165         const struct HksBlob salt = { HKS_RKC_SALT_LEN, (uint8_t *)(ksfDataRkc->rmkSalt) };
166         ret = RkcPbkdf2Hmac(ksfDataRkc->rmkHashAlg, &rawKey, &salt, ksfDataRkc->rmkIter, rmk);
167         HKS_IF_NOT_SUCC_LOGE(ret, "Pbkdf2 failed! ret = 0x%" LOG_PUBLIC "X", ret)
168     } while (0);
169 
170     (void)memset_s(rawKey.data, rawKey.size, 0, rawKey.size);
171     HKS_FREE_BLOB(rawKey);
172     return ret;
173 }
174 
RkcMkCryptV1(const struct HksRkcKsfDataV1 * ksfData,struct HksBlob * plainText,struct HksBlob * cipherText,const bool encrypt)175 static int32_t RkcMkCryptV1(const struct HksRkcKsfDataV1 *ksfData,
176     struct HksBlob *plainText, struct HksBlob *cipherText, const bool encrypt)
177 {
178     struct HksBlob rmk;
179     rmk.data = (uint8_t *)HksMalloc(HKS_RKC_RMK_LEN);
180     HKS_IF_NULL_LOGE_RETURN(rmk.data, HKS_ERROR_MALLOC_FAIL, "Malloc rmk failed!")
181 
182     rmk.size = HKS_RKC_RMK_LEN;
183     (void)memset_s(rmk.data, rmk.size, 0, rmk.size);
184 
185     int32_t ret;
186     do {
187         ret = RkcDeriveRmkV1(&(ksfData->ksfDataRkc), &rmk);
188         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "Derive rmk failed! ret = 0x%" LOG_PUBLIC "X", ret)
189 
190         ret = ExecuteMkCrypt(&(ksfData->ksfDataMk), &rmk, plainText, cipherText, encrypt);
191         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "Crypto mk failed! ret = 0x%" LOG_PUBLIC "X", ret)
192     } while (0);
193 
194     /* the data of root key should be cleared after use */
195     (void)memset_s(rmk.data, rmk.size, 0, rmk.size);
196     HKS_FREE_BLOB(rmk);
197     return ret;
198 }
199 
RkcLoadKsfV1(struct HksBlob * mkBlob)200 static int32_t RkcLoadKsfV1(struct HksBlob *mkBlob)
201 {
202     struct HksRkcKsfDataV1 *validKsfData = (struct HksRkcKsfDataV1 *)HksMalloc(sizeof(struct HksRkcKsfDataV1));
203     if (validKsfData == NULL) {
204         return HKS_ERROR_MALLOC_FAIL;
205     }
206 
207     int32_t ret;
208     do {
209         ret = RkcReadAllKsfV1(validKsfData);
210         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "All rkc ksf file are invalid! ret = 0x%" LOG_PUBLIC "X", ret)
211 
212         RkcRecoverRkTime(validKsfData->ksfDataRkc.rkCreatedTime, validKsfData->ksfDataRkc.rkExpiredTime);
213         RkcRecoverMkTime(validKsfData->ksfDataMk.mkCreatedTime, validKsfData->ksfDataMk.mkExpiredTime);
214 
215         struct HksBlob mkCipherText = { HKS_RKC_MK_CIPHER_TEXT_LEN, (uint8_t *)validKsfData->ksfDataMk.mkCiphertext };
216         ret = RkcMkCryptV1(validKsfData, mkBlob, &mkCipherText, false); /* false: decrypt */
217         HKS_IF_NOT_SUCC_LOGE(ret, "Main key crypt failed! ret = 0x%" LOG_PUBLIC "X", ret)
218     } while (0);
219 
220     HKS_MEMSET_FREE_PTR(validKsfData, sizeof(struct HksRkcKsfDataV1));
221     return ret;
222 }
223 
RkcDeleteAllKsfV1(void)224 static int32_t RkcDeleteAllKsfV1(void)
225 {
226     struct HksProcessInfo processInfo = { {0, NULL}, {0, NULL}, 0, 0, 0 };
227     int32_t ret = GetProcessInfo(&processInfo);
228     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_INTERNAL_ERROR, "get process info failed")
229 
230     struct HksBlob fileNameBlob1 = { strlen("info1.data"), (uint8_t *)"info1.data" };
231 
232     struct HksParamSet *paramSet = NULL;
233     ret = HksRkcBuildParamSet(&paramSet);
234     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "rkc build paramset failed")
235 
236     ret = HksManageStoreDeleteKeyBlob(&processInfo, paramSet, &fileNameBlob1, HKS_STORAGE_TYPE_ROOT_KEY);
237     if ((ret != HKS_SUCCESS) && (ret != HKS_ERROR_NOT_EXIST)) {
238         HKS_LOG_E("delete rkc keystore file failed, ret = %" LOG_PUBLIC "d", ret);
239     }
240 
241     struct HksBlob fileNameBlob2 = { strlen("info2.data"), (uint8_t *)"info2.data" };
242     ret = HksManageStoreDeleteKeyBlob(&processInfo, paramSet, &fileNameBlob2, HKS_STORAGE_TYPE_ROOT_KEY);
243     if ((ret != HKS_SUCCESS) && (ret != HKS_ERROR_NOT_EXIST)) {
244         HKS_LOG_E("delete rkc keystore file failed, ret = %" LOG_PUBLIC "d", ret);
245     }
246 
247     HksFreeParamSet(&paramSet);
248     return ret;
249 }
250 
UpgradeV1ToV2(void)251 int32_t UpgradeV1ToV2(void)
252 {
253     HKS_LOG_I("Rkc ksf is exist, start to load ksf");
254     uint8_t mk[HKS_RKC_MK_LEN] = {0};
255     struct HksBlob tempMkBlob = { HKS_RKC_MK_LEN, mk };
256     int32_t ret = RkcLoadKsfV1(&tempMkBlob);
257     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Load rkc ksf failed! ret = 0x%" LOG_PUBLIC "X", ret)
258 
259     // generate new materials and encrypt main key
260     struct HksKsfDataRkcWithVer *newKsfDataRkcWithVer =
261         (struct HksKsfDataRkcWithVer *)HksMalloc(sizeof(struct HksKsfDataRkcWithVer));
262     struct HksKsfDataMkWithVer *newKsfDataMkWithVer =
263         (struct HksKsfDataMkWithVer *)HksMalloc(sizeof(struct HksKsfDataMkWithVer));
264 
265     do {
266         if (newKsfDataRkcWithVer == NULL || newKsfDataMkWithVer == NULL) {
267             HKS_LOG_E("Malloc rkc or mk ksf data failed!");
268             ret = HKS_ERROR_INSUFFICIENT_MEMORY;
269             break;
270         }
271 
272         FillKsfDataMkWithVer(newKsfDataMkWithVer);
273         ret = FillKsfDataRkcWithVer(newKsfDataRkcWithVer);
274         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "Fill rkc data failed")
275 
276         struct HksBlob cipherTextBlob = { HKS_RKC_MK_CIPHER_TEXT_LEN, newKsfDataMkWithVer->ksfDataMk.mkCiphertext };
277         ret = RkcMkCrypt(&(newKsfDataRkcWithVer->ksfDataRkc), &(newKsfDataMkWithVer->ksfDataMk), &tempMkBlob,
278             &cipherTextBlob, true); /* true: encrypt */
279         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "Encrypt mk failed! ret = 0x%" LOG_PUBLIC "X", ret)
280 
281         /* Initialize rkc keystore file name (mk already done in HksRkcInit) */
282         char rinfo1[] = "rinfo1_v2.data";
283         char rinfo2[] = "rinfo2_v2.data";
284         struct HksKsfAttr ksfAttrRkc = {{ rinfo1, rinfo2 }};
285         ret = InitKsfAttr(&ksfAttrRkc, HKS_KSF_TYPE_RKC);
286         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "Init attribute of rkc keystore file failed! ret = 0x%" LOG_PUBLIC "X", ret)
287 
288         /* Write the root key component and the main key data into all keystore files */
289         ret = RkcWriteAllKsf(newKsfDataRkcWithVer, newKsfDataMkWithVer);
290         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "Write rkc & mk ksf failed! ret = 0x%" LOG_PUBLIC "X", ret)
291 
292         /* delete all old rkc keystore files */
293         (void)RkcDeleteAllKsfV1();
294 
295         ret = RkcMaskMk(&tempMkBlob);
296     } while (0);
297 
298     /* the data of root & main key should be cleared after use */
299     HKS_MEMSET_FREE_PTR(newKsfDataRkcWithVer, sizeof(struct HksKsfDataRkcWithVer));
300     HKS_MEMSET_FREE_PTR(newKsfDataMkWithVer, sizeof(struct HksKsfDataMkWithVer));
301     (void)memset_s(mk, HKS_RKC_MK_LEN, 0, HKS_RKC_MK_LEN);
302     return ret;
303 }
304