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(&paramSet->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