1 /*
2  * Copyright (c) 2021-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_ipc_check.h"
17 
18 #include <stddef.h>
19 
20 #include "hks_common_check.h"
21 #include "hks_client_ipc_serialization.h"
22 #include "hks_log.h"
23 #include "hks_param.h"
24 #include "hks_template.h"
25 
26 #define MIN_CERT_COUNT 3
27 #define MAX_CERT_COUNT 4
28 
HksCheckIpcGenerateKey(const struct HksBlob * keyAlias,const struct HksParamSet * paramSetIn)29 int32_t HksCheckIpcGenerateKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSetIn)
30 {
31     int32_t ret = HksCheckBlobAndParamSet(keyAlias, paramSetIn);
32     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or paramSetIn failed")
33 
34     if ((keyAlias->size > MAX_PROCESS_SIZE) ||
35         ((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) + ALIGN_SIZE(paramSetIn->paramSetSize) +
36         sizeof(uint32_t)) > MAX_PROCESS_SIZE)) {
37         HKS_LOG_E("ipc generate key check size failed");
38         return HKS_ERROR_INVALID_ARGUMENT;
39     }
40 
41     return HKS_SUCCESS;
42 }
43 
HksCheckIpcImportKey(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet,const struct HksBlob * key)44 int32_t HksCheckIpcImportKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
45     const struct HksBlob *key)
46 {
47     int32_t ret = HksCheckBlob2AndParamSet(keyAlias, key, paramSet);
48     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or key or paramSetIn failed")
49 
50     if ((keyAlias->size > MAX_PROCESS_SIZE) || (key->size > MAX_PROCESS_SIZE)) {
51         return HKS_ERROR_INVALID_ARGUMENT;
52     }
53     if ((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) + ALIGN_SIZE(paramSet->paramSetSize) +
54         sizeof(key->size) + ALIGN_SIZE(key->size) > MAX_PROCESS_SIZE)) {
55         return HKS_ERROR_INVALID_ARGUMENT;
56     }
57     return HKS_SUCCESS;
58 }
59 
HksCheckIpcImportWrappedKey(const struct HksBlob * keyAlias,const struct HksBlob * wrappingKeyAlias,const struct HksParamSet * paramSet,const struct HksBlob * wrappedKeyData)60 int32_t HksCheckIpcImportWrappedKey(const struct HksBlob *keyAlias, const struct HksBlob *wrappingKeyAlias,
61     const struct HksParamSet *paramSet, const struct HksBlob *wrappedKeyData)
62 {
63     int32_t ret = HksCheckBlob3AndParamSet(keyAlias, wrappingKeyAlias, wrappedKeyData, paramSet);
64     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or wrappingKeyAlias or wrappedKeyData or paramSet failed")
65 
66     if ((keyAlias->size > MAX_PROCESS_SIZE) || (wrappingKeyAlias->size > MAX_PROCESS_SIZE) ||
67         (wrappedKeyData->size > MAX_PROCESS_SIZE)) {
68         return HKS_ERROR_INVALID_ARGUMENT;
69     }
70 
71     if ((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) +
72          sizeof(wrappingKeyAlias->size) + ALIGN_SIZE(wrappingKeyAlias->size) + ALIGN_SIZE(paramSet->paramSetSize) +
73          sizeof(wrappedKeyData->size) + ALIGN_SIZE(wrappedKeyData->size)) > MAX_PROCESS_SIZE) {
74         return HKS_ERROR_INVALID_ARGUMENT;
75     }
76     return HKS_SUCCESS;
77 }
78 
HksCheckIpcDeleteKey(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet)79 int32_t HksCheckIpcDeleteKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet)
80 {
81     int32_t ret = HksCheckBlobAndParamSet(keyAlias, paramSet);
82     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or paramSet failed")
83 
84     if (keyAlias->size > MAX_PROCESS_SIZE) {
85         return HKS_ERROR_INVALID_ARGUMENT;
86     }
87 
88     if (((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) +
89         ALIGN_SIZE(paramSet->paramSetSize)) > MAX_PROCESS_SIZE)) {
90         HKS_LOG_E("ipc delete key check size failed");
91         return HKS_ERROR_INVALID_ARGUMENT;
92     }
93     return HKS_SUCCESS;
94 }
95 
HksCheckIpcExportPublicKey(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet,const struct HksBlob * key)96 int32_t HksCheckIpcExportPublicKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
97     const struct HksBlob *key)
98 {
99     int32_t ret = HksCheckBlob2AndParamSet(keyAlias, key, paramSet);
100     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or key or paramSetIn failed")
101 
102     if (keyAlias->size > MAX_PROCESS_SIZE) {
103         return HKS_ERROR_INVALID_ARGUMENT;
104     }
105     if ((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) + sizeof(key->size) +
106         ALIGN_SIZE(paramSet->paramSetSize)) > MAX_PROCESS_SIZE) {
107         HKS_LOG_E("ipc export public key check size failed");
108         return HKS_ERROR_INVALID_ARGUMENT;
109     }
110     return HKS_SUCCESS;
111 }
112 
HksCheckIpcGetKeyParamSet(const struct HksBlob * keyAlias,const struct HksParamSet * paramSetIn,struct HksParamSet * paramSetOut)113 int32_t HksCheckIpcGetKeyParamSet(const struct HksBlob *keyAlias, const struct HksParamSet *paramSetIn,
114     struct HksParamSet *paramSetOut)
115 {
116     int32_t ret = HksCheckBlobAndParamSet(keyAlias, paramSetIn);
117     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or paramSetIn failed")
118 
119     if (keyAlias->size > MAX_PROCESS_SIZE) {
120         return HKS_ERROR_INVALID_ARGUMENT;
121     }
122     if (paramSetOut->paramSetSize == 0) {
123         return HKS_ERROR_INVALID_ARGUMENT;
124     }
125     if ((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) + sizeof(paramSetOut->paramSetSize) +
126         ALIGN_SIZE(paramSetIn->paramSetSize)) > MAX_PROCESS_SIZE) {
127         HKS_LOG_E("ipc get key paramset check size failed");
128         return HKS_ERROR_INVALID_ARGUMENT;
129     }
130     return HKS_SUCCESS;
131 }
132 
HksCheckIpcKeyExist(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet)133 int32_t HksCheckIpcKeyExist(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet)
134 {
135     int32_t ret = HksCheckBlobAndParamSet(keyAlias, paramSet);
136     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or paramSet failed")
137 
138     if (keyAlias->size > MAX_PROCESS_SIZE) {
139         return HKS_ERROR_INVALID_ARGUMENT;
140     }
141 
142     if (((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) +
143         ALIGN_SIZE(paramSet->paramSetSize)) > MAX_PROCESS_SIZE)) {
144         HKS_LOG_E("ipc key exist check size failed");
145         return HKS_ERROR_INVALID_ARGUMENT;
146     }
147     return HKS_SUCCESS;
148 }
149 
HksCheckIpcAgreeKey(const struct HksParamSet * paramSet,const struct HksBlob * privateKey,const struct HksBlob * peerPublicKey,const struct HksBlob * agreedKey)150 int32_t HksCheckIpcAgreeKey(const struct HksParamSet *paramSet, const struct HksBlob *privateKey,
151     const struct HksBlob *peerPublicKey, const struct HksBlob *agreedKey)
152 {
153     int32_t ret = HksCheckBlob3AndParamSet(privateKey, peerPublicKey, agreedKey, paramSet);
154     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check key or paramSetIn failed")
155 
156     if ((privateKey->size > MAX_PROCESS_SIZE) || (peerPublicKey->size > MAX_PROCESS_SIZE)) {
157         return HKS_ERROR_INVALID_ARGUMENT;
158     }
159     if ((ALIGN_SIZE(paramSet->paramSetSize) + sizeof(privateKey->size) + ALIGN_SIZE(privateKey->size) +
160         sizeof(peerPublicKey->size) + ALIGN_SIZE(peerPublicKey->size) + sizeof(agreedKey->size) > MAX_PROCESS_SIZE)) {
161         return HKS_ERROR_INVALID_ARGUMENT;
162     }
163     return HKS_SUCCESS;
164 }
165 
HksCheckIpcDeriveKey(const struct HksParamSet * paramSet,const struct HksBlob * mainKey,const struct HksBlob * derivedKey)166 int32_t HksCheckIpcDeriveKey(const struct HksParamSet *paramSet, const struct HksBlob *mainKey,
167     const struct HksBlob *derivedKey)
168 {
169     int32_t ret = HksCheckBlob2AndParamSet(mainKey, derivedKey, paramSet);
170     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check key or paramSetIn failed")
171 
172     if (mainKey->size > MAX_PROCESS_SIZE) {
173         return HKS_ERROR_INVALID_ARGUMENT;
174     }
175     if ((ALIGN_SIZE(paramSet->paramSetSize) + sizeof(mainKey->size) + ALIGN_SIZE(mainKey->size) +
176         sizeof(derivedKey->size)) > MAX_PROCESS_SIZE) {
177         return HKS_ERROR_INVALID_ARGUMENT;
178     }
179     return HKS_SUCCESS;
180 }
181 
HksCheckIpcGetKeyInfoList(const struct HksKeyInfo * keyInfoList,const struct HksParamSet * paramSet,uint32_t listCount)182 int32_t HksCheckIpcGetKeyInfoList(const struct HksKeyInfo *keyInfoList, const struct HksParamSet *paramSet,
183     uint32_t listCount)
184 {
185     HKS_IF_NOT_SUCC_RETURN(HksCheckParamSet(paramSet, paramSet->paramSetSize), HKS_ERROR_INVALID_ARGUMENT)
186 
187     enum {
188         HKS_GET_KEY_LIST_MAX_COUNT = 2048U,
189     };
190     if (listCount == 0 || listCount > HKS_GET_KEY_LIST_MAX_COUNT) {
191         HKS_LOG_E("invalid listCount %" LOG_PUBLIC "u", listCount);
192         return HKS_ERROR_INVALID_ARGUMENT;
193     }
194 
195     if (listCount > (MAX_PROCESS_SIZE - ALIGN_SIZE(paramSet->paramSetSize) -
196         sizeof(uint32_t)) / (sizeof(uint32_t) + sizeof(uint32_t))) {
197         HKS_LOG_E("ipc get key info check size failed");
198         return HKS_ERROR_INVALID_ARGUMENT;
199     }
200 
201     for (uint32_t i = 0; i < listCount; ++i) {
202         if ((CheckBlob(&keyInfoList[i].alias) != HKS_SUCCESS) ||
203             (keyInfoList[i].paramSet == NULL) || (keyInfoList[i].paramSet->paramSetSize == 0)) {
204             return HKS_ERROR_INVALID_ARGUMENT;
205         }
206     }
207 
208     uint32_t keyInfoBufSize = sizeof(listCount);
209     for (uint32_t i = 0; i < listCount; ++i) {
210         if (IsAdditionOverflow(keyInfoBufSize, sizeof(keyInfoList[i].alias.size))) {
211             return HKS_ERROR_INVALID_ARGUMENT;
212         }
213         keyInfoBufSize += sizeof(keyInfoList[i].alias.size);
214         if ((IsAdditionOverflow(keyInfoList[i].alias.size, DEFAULT_ALIGN_MASK_SIZE)) ||
215             (IsAdditionOverflow(keyInfoList[i].paramSet->paramSetSize, DEFAULT_ALIGN_MASK_SIZE))) {
216             return HKS_ERROR_INVALID_ARGUMENT;
217         }
218         if (IsAdditionOverflow(keyInfoBufSize, ALIGN_SIZE(keyInfoList[i].alias.size))) {
219             return HKS_ERROR_INVALID_ARGUMENT;
220         }
221         keyInfoBufSize += ALIGN_SIZE(keyInfoList[i].alias.size);
222         if (IsAdditionOverflow(keyInfoBufSize, ALIGN_SIZE(keyInfoList[i].paramSet->paramSetSize))) {
223             return HKS_ERROR_INVALID_ARGUMENT;
224         }
225         keyInfoBufSize += ALIGN_SIZE(keyInfoList[i].paramSet->paramSetSize);
226     }
227     return HKS_SUCCESS;
228 }
229 
HksCheckIpcCertificateChain(const struct HksBlob * keyAlias,const struct HksParamSet * paramSet,const struct HksCertChain * certChain)230 int32_t HksCheckIpcCertificateChain(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet,
231     const struct HksCertChain *certChain)
232 {
233     if ((certChain->certs == NULL) || (certChain->certsCount < MIN_CERT_COUNT) ||
234         (certChain->certsCount > MAX_CERT_COUNT)) {
235         return HKS_ERROR_INVALID_ARGUMENT;
236     }
237     HKS_IF_NOT_SUCC_RETURN(HksCheckParamSet(paramSet, paramSet->paramSetSize), HKS_ERROR_INVALID_ARGUMENT)
238     if ((keyAlias->size > MAX_PROCESS_SIZE) ||
239         ((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) +
240         ALIGN_SIZE(paramSet->paramSetSize)) > MAX_PROCESS_SIZE)) {
241         return HKS_ERROR_INVALID_ARGUMENT;
242     }
243 
244     uint32_t certBufSize = sizeof(certChain->certsCount);
245     for (uint32_t i = 0; i < certChain->certsCount; ++i) {
246         if (IsAdditionOverflow(certBufSize, sizeof(certChain->certs[i].size))) {
247             return HKS_ERROR_INVALID_ARGUMENT;
248         }
249         certBufSize += sizeof(certChain->certs[i].size);
250 
251         if (IsAdditionOverflow(certChain->certs[i].size, DEFAULT_ALIGN_MASK_SIZE)) {
252             return HKS_ERROR_INVALID_ARGUMENT;
253         }
254         if (IsAdditionOverflow(certBufSize, ALIGN_SIZE(certChain->certs[i].size))) {
255             return HKS_ERROR_INVALID_ARGUMENT;
256         }
257         certBufSize += ALIGN_SIZE(certChain->certs[i].size);
258     }
259     return HKS_SUCCESS;
260 }
261 
HksCheckIpcListAliases(const struct HksParamSet * paramSet)262 int32_t HksCheckIpcListAliases(const struct HksParamSet *paramSet)
263 {
264     HKS_IF_NOT_SUCC_RETURN(HksCheckParamSet(paramSet, paramSet->paramSetSize), HKS_ERROR_INVALID_ARGUMENT)
265 
266     if ((ALIGN_SIZE(paramSet->paramSetSize) > MAX_PROCESS_SIZE)) {
267         return HKS_ERROR_INVALID_ARGUMENT;
268     }
269     return HKS_SUCCESS;
270 }
271 
HksCheckIpcRenameKeyAlias(const struct HksBlob * oldKeyAlias,const struct HksParamSet * paramSet,const struct HksBlob * newKeyAlias)272 int32_t HksCheckIpcRenameKeyAlias(const struct HksBlob *oldKeyAlias, const struct HksParamSet *paramSet,
273     const struct HksBlob *newKeyAlias)
274 {
275     int32_t ret = HksCheckBlob2AndParamSet(oldKeyAlias, newKeyAlias, paramSet);
276     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or paramSet failed")
277 
278     if ((MAX_PROCESS_SIZE - sizeof(oldKeyAlias->size) - ALIGN_SIZE(oldKeyAlias->size) -
279         sizeof(newKeyAlias->size) - ALIGN_SIZE(newKeyAlias->size) < ALIGN_SIZE(paramSet->paramSetSize))) {
280         HKS_LOG_E("ipc rename key alias check size failed");
281         return HKS_ERROR_INVALID_ARGUMENT;
282     }
283     return HKS_SUCCESS;
284 }
285 
HksCheckIpcChangeStorageLevel(const struct HksBlob * keyAlias,const struct HksParamSet * srcParamSet,const struct HksParamSet * destParamSet)286 int32_t HksCheckIpcChangeStorageLevel(const struct HksBlob *keyAlias, const struct HksParamSet *srcParamSet,
287     const struct HksParamSet *destParamSet)
288 {
289     int32_t ret = HksCheckBlobAndParamSet2(keyAlias, srcParamSet, destParamSet);
290     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "check keyAlias or paramSet failed")
291 
292     if (keyAlias->size > MAX_PROCESS_SIZE) {
293         return HKS_ERROR_INVALID_ARGUMENT;
294     }
295 
296     if ((sizeof(keyAlias->size) + ALIGN_SIZE(keyAlias->size) + ALIGN_SIZE(srcParamSet->paramSetSize) +
297         ALIGN_SIZE(destParamSet->paramSetSize)) > MAX_PROCESS_SIZE) {
298         HKS_LOG_E("ipc change storage level check size failed");
299         return HKS_ERROR_INVALID_ARGUMENT;
300     }
301 
302     return HKS_SUCCESS;
303 }