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(¶mSet);
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(¶mSet);
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