1 /*
2 * Copyright (c) 2023-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 #include "hks_chipset_platform_decrypt.h"
16
17 #include "hks_chipset_platform_key.h"
18 #include "hks_client_service_adapter.h"
19 #include "hks_crypto_hal.h"
20 #include "hks_log.h"
21 #include "hks_mem.h"
22 #include "hks_param.h"
23 #include "hks_template.h"
24 #include "hks_type.h"
25
26 #include "securec.h"
27 #include <stdbool.h>
28
29 #ifdef HKS_SUPPORT_CHIPSET_PLATFORM_DECRYPT
30
31 static const uint32_t ORDERED_VALID_TAGS[PLATFORM_KEY_INPUT_PARAMS_COUNT] = {
32 HKS_TAG_SALT,
33 HKS_TAG_PEER_PUBLIC_KEY,
34 HKS_TAG_INFO,
35 HKS_TAG_IV,
36 HKS_TAG_ASSOCIATED_DATA,
37 HKS_TAG_AE_TAG,
38 HKS_TAG_CIPHER_TEXT,
39 };
40
CheckParams(const struct HksParamSet * paramSet)41 static int32_t CheckParams(const struct HksParamSet *paramSet)
42 {
43 if (paramSet == NULL) {
44 HKS_LOG_E("invalid paramSet");
45 return HKS_ERROR_INVALID_ARGUMENT;
46 }
47 int32_t ret = HksCheckParamSet(paramSet, paramSet->paramSetSize);
48 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_INVALID_ARGUMENT, "Check params failed")
49
50 if (paramSet->paramsCnt != PLATFORM_KEY_INPUT_PARAMS_COUNT) {
51 HKS_LOG_E("invalid params count");
52 return HKS_ERROR_INVALID_ARGUMENT;
53 }
54
55 for (uint32_t i = 0; i < PLATFORM_KEY_INPUT_PARAMS_COUNT; ++i) {
56 if (GetTagType((enum HksTag)(paramSet->params[i].tag)) != HKS_TAG_TYPE_BYTES) {
57 HKS_LOG_E("params not bytes");
58 return HKS_ERROR_INVALID_ARGUMENT;
59 }
60 ret = CheckBlob(¶mSet->params[i].blob);
61 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, HKS_ERROR_INVALID_ARGUMENT, "Check params failed")
62 }
63
64 // check whether all required tags are present or duplicated
65 uint32_t uniqCount = 0;
66 for (uint32_t i = 0; i < PLATFORM_KEY_INPUT_PARAMS_COUNT; ++i) {
67 for (uint32_t j = 0; j < PLATFORM_KEY_INPUT_PARAMS_COUNT; ++j) {
68 if (paramSet->params[j].tag == ORDERED_VALID_TAGS[i]) {
69 uniqCount++;
70 break;
71 }
72 }
73 }
74
75 if (uniqCount != PLATFORM_KEY_INPUT_PARAMS_COUNT) {
76 HKS_LOG_E("param tags repeat");
77 return HKS_ERROR_INVALID_ARGUMENT;
78 }
79 return ret;
80 }
81
CheckText(const struct HksBlob * cipherText,const struct HksBlob * plainText)82 static int32_t CheckText(const struct HksBlob *cipherText, const struct HksBlob *plainText)
83 {
84 if (cipherText->size != plainText->size) {
85 HKS_LOG_E("cipher text len %" LOG_PUBLIC "d does not equal to plain text len %" LOG_PUBLIC "d",
86 cipherText->size, plainText->size);
87 return HKS_ERROR_INVALID_ARGUMENT;
88 }
89 if (plainText->size > PLATFORM_KEY_TEXT_MAX_LEN || plainText->size < PLATFORM_KEY_TEXT_MIN_LEN) {
90 HKS_LOG_E("plain text length out of range %" LOG_PUBLIC "d", plainText->size);
91 return HKS_ERROR_INVALID_ARGUMENT;
92 }
93 return HKS_SUCCESS;
94 }
95
DoGenEcdhSharedKey(const struct HksParamSet * paramSet,enum HksChipsetPlatformDecryptScene scene,struct HksBlob * sharedKey)96 static int32_t DoGenEcdhSharedKey(const struct HksParamSet *paramSet, enum HksChipsetPlatformDecryptScene scene,
97 struct HksBlob *sharedKey)
98 {
99 struct HksBlob saltPadding = { .size = PLATFORM_KEY_SALT_SIZE,
100 .data = (uint8_t *)HksMalloc(PLATFORM_KEY_SALT_SIZE) };
101 HKS_IF_NULL_RETURN(saltPadding.data, HKS_ERROR_MALLOC_FAIL);
102 int32_t ret;
103 do {
104 struct HksParam *saltParam = NULL;
105 ret = HksGetParam(paramSet, HKS_TAG_SALT, &saltParam);
106 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get salt fail");
107
108 struct HksParam *peerPkParam = NULL;
109 ret = HksGetParam(paramSet, HKS_TAG_PEER_PUBLIC_KEY, &peerPkParam);
110 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get tmp pk fail");
111
112 if (saltParam->blob.size != PLATFORM_KEY_SALT_SIZE ||
113 peerPkParam->blob.size != PLATFORM_KEY_PLATFORM_PUB_KEY_SIZE) {
114 ret = HKS_ERROR_INVALID_ARGUMENT;
115 break;
116 }
117 (void)(memcpy_s(saltPadding.data, PLATFORM_KEY_SALT_SIZE, saltParam->blob.data, PLATFORM_KEY_SALT_SIZE));
118 if (scene == HKS_CHIPSET_PLATFORM_DECRYPT_SCENE_TA_TO_TA) {
119 saltPadding.data[PLATFORM_KEY_SALT_SIZE - 1] = PLATFORM_KEY_SALT_PADDING_BYTE_TA_TO_TA;
120 }
121 ret = HksChipsetPlatformDeriveKeyAndEcdh(&peerPkParam->blob, &saltPadding, sharedKey);
122 } while (false);
123 HKS_MEMSET_FREE_BLOB(saltPadding);
124 return ret;
125 }
126
DoHmacSha256(const struct HksBlob * hmacMsg,const struct HksBlob * sharedKey,struct HksBlob * wrappedKey)127 static int32_t DoHmacSha256(const struct HksBlob *hmacMsg,
128 const struct HksBlob *sharedKey, struct HksBlob *wrappedKey)
129 {
130 if (hmacMsg->size != PLATFORM_KEY_HMAC_MESSAGE_SIZE) {
131 HKS_LOG_E("invalid hmacMsg->size %" LOG_PUBLIC "d", hmacMsg->size);
132 return HKS_ERROR_INVALID_ARGUMENT;
133 }
134 return HksCryptoHalHmac(sharedKey, HKS_DIGEST_SHA256, hmacMsg, wrappedKey);
135 }
136
DoAesDecrypt(const struct HksParamSet * paramSecureSet,const struct HksBlob * wrappedKey,struct HksBlob * plainText)137 static int32_t DoAesDecrypt(const struct HksParamSet *paramSecureSet,
138 const struct HksBlob *wrappedKey, struct HksBlob *plainText)
139 {
140 struct HksParam *cipherTextParam = NULL;
141 int32_t ret = HksGetParam(paramSecureSet, HKS_TAG_CIPHER_TEXT, &cipherTextParam);
142 HKS_IF_NOT_SUCC_RETURN(ret, ret);
143
144 struct HksParam *ivParam = NULL;
145 ret = HksGetParam(paramSecureSet, HKS_TAG_IV, &ivParam);
146 HKS_IF_NOT_SUCC_RETURN(ret, ret);
147
148 struct HksParam *aadParam = NULL;
149 ret = HksGetParam(paramSecureSet, HKS_TAG_ASSOCIATED_DATA, &aadParam);
150 HKS_IF_NOT_SUCC_RETURN(ret, ret);
151
152 struct HksParam *tagParam = NULL;
153 ret = HksGetParam(paramSecureSet, HKS_TAG_AE_TAG, &tagParam);
154 HKS_IF_NOT_SUCC_RETURN(ret, ret);
155
156 struct HksBlob aad = aadParam->blob;
157 struct HksBlob iv = ivParam->blob;
158 struct HksBlob tag = tagParam->blob;
159 struct HksBlob cipherText = cipherTextParam->blob;
160 if (aad.size != PLATFORM_KEY_AAD_SIZE) {
161 HKS_LOG_E("invalid aad size %" LOG_PUBLIC "d", aad.size);
162 return HKS_ERROR_INVALID_ARGUMENT;
163 }
164 if (iv.size != PLATFORM_KEY_IV_SIZE) {
165 HKS_LOG_E("invalid iv size %" LOG_PUBLIC "d", iv.size);
166 return HKS_ERROR_INVALID_ARGUMENT;
167 }
168 if (tag.size != PLATFORM_KEY_TAG_SIZE) {
169 HKS_LOG_E("invalid tag size %" LOG_PUBLIC "d", tag.size);
170 return HKS_ERROR_INVALID_ARGUMENT;
171 }
172
173 struct HksAeadParam aeadParam = {
174 .nonce = iv,
175 .aad = aad,
176 .tagDec = tag,
177 .payloadLen = cipherText.size,
178 };
179 struct HksUsageSpec decryptSpec = {
180 .algType = HKS_ALG_AES,
181 .mode = HKS_MODE_GCM,
182 .padding = HKS_PADDING_NONE,
183 .purpose = HKS_KEY_PURPOSE_DECRYPT,
184 .algParam = (void *)&aeadParam,
185 };
186 return HksCryptoHalDecrypt(wrappedKey, &decryptSpec, &cipherText, plainText);
187 }
188
CheckInput(const struct HksParamSet * paramSet,struct HksBlob * plainText,enum HksChipsetPlatformDecryptScene scene)189 static int32_t CheckInput(const struct HksParamSet *paramSet, struct HksBlob *plainText,
190 enum HksChipsetPlatformDecryptScene scene)
191 {
192 // basic check for plainText and paramSet
193 int32_t ret = CheckBlob(plainText);
194 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Check plainText failed")
195
196 ret = CheckParams(paramSet);
197 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Check params failed")
198
199 // check scene
200 if (scene != HKS_CHIPSET_PLATFORM_DECRYPT_SCENE_TA_TO_TA) {
201 HKS_LOG_E("invalid scene");
202 return HKS_ERROR_INVALID_ARGUMENT;
203 }
204
205 // specialized check for text
206 struct HksParam *cipherTextParam = NULL;
207 ret = HksGetParam(paramSet, HKS_TAG_CIPHER_TEXT, &cipherTextParam);
208 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "get param cipher text failed")
209 ret = CheckText(&cipherTextParam->blob, plainText);
210 if (ret != HKS_SUCCESS) {
211 return HKS_ERROR_INVALID_ARGUMENT;
212 }
213 return HKS_SUCCESS;
214 }
215
HuksCoreChipsetPlatformDecrypt(const struct HksParamSet * paramSet,enum HksChipsetPlatformDecryptScene scene,struct HksBlob * plainText)216 int32_t HuksCoreChipsetPlatformDecrypt(const struct HksParamSet *paramSet,
217 enum HksChipsetPlatformDecryptScene scene, struct HksBlob *plainText)
218 {
219 int32_t ret = CheckInput(paramSet, plainText, scene);
220 HKS_IF_NOT_SUCC_RETURN(ret, ret);
221
222 // malloc for key
223 struct HksBlob sharedKey = { .size = PLATFORM_KEY_SHARED_KEY_SIZE,
224 .data = (uint8_t *)HksMalloc(PLATFORM_KEY_SHARED_KEY_SIZE) };
225 if (sharedKey.data == NULL) {
226 return HKS_ERROR_INSUFFICIENT_MEMORY;
227 }
228
229 struct HksBlob wrappedKey = { .size = PLATFORM_KEY_WRAPPED_KEY_SIZE,
230 .data = (uint8_t *)HksMalloc(PLATFORM_KEY_WRAPPED_KEY_SIZE) };
231 if (wrappedKey.data == NULL) {
232 HKS_MEMSET_FREE_BLOB(sharedKey);
233 return HKS_ERROR_INSUFFICIENT_MEMORY;
234 }
235
236 do {
237 // do ecdh to get sharedKey
238 HKS_LOG_I("start ecdh");
239 ret = DoGenEcdhSharedKey(paramSet, scene, &sharedKey);
240 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "ecdh get sharedKey failed %" LOG_PUBLIC "d", ret)
241
242 // do hmac to get wrappedKey
243 struct HksParam *customInfoParam = NULL;
244 ret = HksGetParam(paramSet, HKS_TAG_INFO, &customInfoParam);
245 HKS_IF_NOT_SUCC_BREAK(ret)
246
247 HKS_LOG_I("start hmac");
248 ret = DoHmacSha256(&customInfoParam->blob, &sharedKey, &wrappedKey);
249 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "hmac get wrappedKey failed %" LOG_PUBLIC "d", ret)
250
251 // do aes decrypt
252 HKS_LOG_I("start decrypt");
253 ret = DoAesDecrypt(paramSet, &wrappedKey, plainText);
254 HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "aes decrypt failed %" LOG_PUBLIC "d", ret)
255 } while (false);
256
257 HKS_MEMSET_FREE_BLOB(sharedKey);
258 HKS_MEMSET_FREE_BLOB(wrappedKey);
259 return ret;
260 }
261
HuksCoreExportChipsetPlatformPublicKey(const struct HksBlob * salt,enum HksChipsetPlatformDecryptScene scene,struct HksBlob * publicKey)262 int32_t HuksCoreExportChipsetPlatformPublicKey(const struct HksBlob *salt,
263 enum HksChipsetPlatformDecryptScene scene, struct HksBlob *publicKey)
264 {
265 if (CheckBlob(salt) != HKS_SUCCESS || CheckBlob(publicKey) != HKS_SUCCESS) {
266 HKS_LOG_E("invalid input salt or pk empty blob");
267 return HKS_ERROR_INVALID_ARGUMENT;
268 }
269 if (salt->size != PLATFORM_KEY_SALT_SIZE || publicKey->size != PLATFORM_KEY_PLATFORM_PUB_KEY_SIZE ||
270 scene != HKS_CHIPSET_PLATFORM_DECRYPT_SCENE_TA_TO_TA) {
271 HKS_LOG_E("invalid input salt sz %" LOG_PUBLIC "d pk sz %" LOG_PUBLIC "d scene %" LOG_PUBLIC "d",
272 salt->size, publicKey->size, scene);
273 return HKS_ERROR_INVALID_ARGUMENT;
274 }
275 struct HksBlob saltPadding = { .size = PLATFORM_KEY_SALT_SIZE,
276 .data = (uint8_t *)HksMalloc(PLATFORM_KEY_SALT_SIZE) };
277 HKS_IF_NULL_LOGE_RETURN(saltPadding.data, HKS_ERROR_MALLOC_FAIL, "malloc salt padding fail");
278 (void)memcpy_s(saltPadding.data, PLATFORM_KEY_SALT_SIZE, salt->data, PLATFORM_KEY_SALT_SIZE);
279 saltPadding.data[PLATFORM_KEY_SALT_SIZE - 1] = PLATFORM_KEY_SALT_PADDING_BYTE_TA_TO_TA;
280 int32_t ret = HksChipsetPlatformDerivePubKey(&saltPadding, publicKey);
281 HKS_MEMSET_FREE_BLOB(saltPadding);
282 return ret;
283 }
284
285 #endif // HKS_SUPPORT_CHIPSET_PLATFORM_DECRYPT
286