1 /*
2  * Copyright (c) 2022 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 "cert_manager_check.h"
17 
18 #include <ctype.h>
19 
20 #include "cert_manager.h"
21 #include "cert_manager_permission_check.h"
22 #include "cert_manager_uri.h"
23 #include "cm_log.h"
24 
CheckUri(const struct CmBlob * keyUri)25 int32_t CheckUri(const struct CmBlob *keyUri)
26 {
27     if (CmCheckBlob(keyUri) != CM_SUCCESS) {
28         CM_LOG_E("invalid uri");
29         return CMR_ERROR_INVALID_ARGUMENT;
30     }
31 
32     if (keyUri->size > MAX_AUTH_LEN_URI) {
33         CM_LOG_E("invalid uri len:%u", keyUri->size);
34         return CMR_ERROR_INVALID_ARGUMENT;
35     }
36 
37     for (uint32_t i = 1; i < keyUri->size; ++i) { /* from index 1 has '\0' */
38         if (keyUri->data[i] == 0) {
39             return CM_SUCCESS;
40         }
41     }
42     return CMR_ERROR_INVALID_ARGUMENT;
43 }
44 
CmServiceGetSystemCertListCheck(const uint32_t store)45 int32_t CmServiceGetSystemCertListCheck(const uint32_t store)
46 {
47     if (store != CM_SYSTEM_TRUSTED_STORE) {
48         CM_LOG_E("invalid input arguments store:%u", store);
49         return CMR_ERROR_INVALID_ARGUMENT;
50     }
51 
52     if (!CmHasCommonPermission()) {
53         CM_LOG_E("permission check failed");
54         return CMR_ERROR_PERMISSION_DENIED;
55     }
56 
57     return CM_SUCCESS;
58 }
59 
CmServiceGetSystemCertCheck(const uint32_t store,const struct CmBlob * certUri)60 int32_t CmServiceGetSystemCertCheck(const uint32_t store, const struct CmBlob *certUri)
61 {
62     if (store != CM_SYSTEM_TRUSTED_STORE) {
63         CM_LOG_E("invalid input arguments store:%u", store);
64         return CMR_ERROR_INVALID_ARGUMENT;
65     }
66 
67     if (CheckUri(certUri) != CM_SUCCESS) {
68         CM_LOG_E("invalid input arguments");
69         return CMR_ERROR_INVALID_ARGUMENT;
70     }
71 
72     if (!CmHasCommonPermission()) {
73         CM_LOG_E("permission check failed");
74         return CMR_ERROR_PERMISSION_DENIED;
75     }
76 
77     return CM_SUCCESS;
78 }
79 
CmServiceSetCertStatusCheck(const uint32_t store,const struct CmBlob * certUri,const uint32_t status)80 int32_t CmServiceSetCertStatusCheck(const uint32_t store, const struct CmBlob *certUri, const uint32_t status)
81 {
82     if (store != CM_SYSTEM_TRUSTED_STORE) {
83         CM_LOG_E("invalid input arguments store:%u", store);
84         return CMR_ERROR_INVALID_ARGUMENT;
85     }
86 
87     if (CheckUri(certUri) != CM_SUCCESS) {
88         CM_LOG_E("invalid input arguments");
89         return CMR_ERROR_INVALID_ARGUMENT;
90     }
91 
92     if ((status != 0) && (status != 1)) {
93         CM_LOG_E("invalid input status:%u", status);
94         return CMR_ERROR_INVALID_ARGUMENT;
95     }
96 
97     if (!CmHasPrivilegedPermission() || !CmHasCommonPermission()) {
98         CM_LOG_E("permission check failed");
99         return CMR_ERROR_PERMISSION_DENIED;
100     }
101 
102     if (!CmIsSystemApp()) {
103         CM_LOG_E("set cert status: caller is not system app");
104         return CMR_ERROR_NOT_SYSTEMP_APP;
105     }
106 
107     return CM_SUCCESS;
108 }
109 
CmCheckAppCert(const struct CmBlob * appCert)110 static int32_t CmCheckAppCert(const struct CmBlob *appCert)
111 {
112     if (CmCheckBlob(appCert) != CM_SUCCESS) {
113         CM_LOG_E("appCert blob is invalid");
114         return CMR_ERROR_INVALID_ARGUMENT;
115     }
116 
117     if (appCert->size > MAX_LEN_APP_CERT) {
118         CM_LOG_E("appCert size max check fail, appCert size:%u", appCert->size);
119         return CMR_ERROR_INVALID_ARGUMENT;
120     }
121     return CM_SUCCESS;
122 }
123 
CmCheckAppCertPwd(const struct CmBlob * appCertPwd)124 static int32_t CmCheckAppCertPwd(const struct CmBlob *appCertPwd)
125 {
126     if (CmCheckBlob(appCertPwd) != CM_SUCCESS) {
127         CM_LOG_E("appCertPwd blob is invalid");
128         return CMR_ERROR_INVALID_ARGUMENT;
129     }
130 
131     if (appCertPwd->size > MAX_LEN_APP_CERT_PASSWD) {
132         CM_LOG_E("appCertPwd size max check fail, appCertPwd size:%u", appCertPwd->size);
133         return CMR_ERROR_INVALID_ARGUMENT;
134     }
135 
136     if (CheckUri(appCertPwd) != CM_SUCCESS) {
137         CM_LOG_E("appCertPwd data check fail");
138         return CMR_ERROR_INVALID_ARGUMENT;
139     }
140     return CM_SUCCESS;
141 }
142 
AppCertCheckBlobValid(const struct CmBlob * data)143 static bool AppCertCheckBlobValid(const struct CmBlob *data)
144 {
145     for (uint32_t i = 0; i < data->size; i++) {
146         if ((i > 0) && (data->data[i] == '\0')) { /* from index 1 has '\0' */
147             CM_LOG_D("data has string end character");
148             return true;
149         }
150 
151         if ((!isalnum(data->data[i])) && (data->data[i] != '_')) { /* has invalid character */
152             CM_LOG_E("data include invalid character");
153             return false;
154         }
155     }
156 
157     CM_LOG_E("data has no string end character");
158     return false;
159 }
160 
CmCheckCertAlias(const struct CmBlob * certAlias,uint32_t store)161 static int32_t CmCheckCertAlias(const struct CmBlob *certAlias, uint32_t store)
162 {
163     if (CmCheckBlob(certAlias) != CM_SUCCESS) {
164         CM_LOG_E("certAlias blob is invalid");
165         return CMR_ERROR_INVALID_ARGUMENT;
166     }
167 
168     if (certAlias->size > MAX_LEN_CERT_ALIAS) {
169         CM_LOG_E("alias size is too large");
170         return CMR_ERROR_INVALID_ARGUMENT;
171     }
172 
173     if ((store == CM_PRI_CREDENTIAL_STORE) && (certAlias->size > MAX_LEN_PRI_CRED_ALIAS)) {
174         CM_LOG_E("pri_cred: alias size is too large");
175         return CMR_ERROR_INVALID_ARGUMENT;
176     }
177 
178     if ((store != CM_PRI_CREDENTIAL_STORE) && (strcmp("", (char *)certAlias->data) == 0)) {
179         CM_LOG_D("cert alias is empty string");
180         return CM_SUCCESS;
181     }
182 
183     if (!AppCertCheckBlobValid(certAlias)) {
184         CM_LOG_E("certAlias data check fail");
185         return CMR_ERROR_INVALID_ARGUMENT;
186     }
187     return CM_SUCCESS;
188 }
189 
CmCheckUserIdAndUpdateContext(const uint32_t inputUserId,uint32_t * callerUserId)190 static bool CmCheckUserIdAndUpdateContext(const uint32_t inputUserId, uint32_t *callerUserId)
191 {
192     if (*callerUserId == 0) { /* caller is sa */
193         if (inputUserId == 0 || inputUserId == INIT_INVALID_VALUE) {
194             CM_LOG_E("caller is sa, input userId %u is invalid", inputUserId);
195             return false;
196         }
197         CM_LOG_D("update caller userId from %u to %u", *callerUserId, inputUserId);
198         *callerUserId = inputUserId;
199         return true;
200     }
201 
202     /* caller is hap */
203     if (inputUserId != INIT_INVALID_VALUE) {
204         CM_LOG_E("caller is hap, input userId %u is not supported", inputUserId);
205         return false;
206     }
207     return true;
208 }
209 
CmServiceInstallAppCertCheck(const struct CmAppCertParam * certParam,struct CmContext * cmContext)210 int32_t CmServiceInstallAppCertCheck(const struct CmAppCertParam *certParam, struct CmContext *cmContext)
211 {
212     if ((certParam == NULL) || (cmContext == NULL)) {
213         return CMR_ERROR_INVALID_ARGUMENT;
214     }
215 
216     if (CM_STORE_CHECK(certParam->store)) {
217         CM_LOG_E("CmInstallAppCertCheck store check fail, store:%u", certParam->store);
218         return CMR_ERROR_INVALID_ARGUMENT;
219     }
220 
221     int32_t ret = CmCheckAppCert(certParam->appCert);
222     if (ret != CM_SUCCESS) {
223         return ret;
224     }
225 
226     ret = CmCheckAppCertPwd(certParam->appCertPwd);
227     if (ret != CM_SUCCESS) {
228         return ret;
229     }
230 
231     ret = CmCheckCertAlias(certParam->certAlias, certParam->store);
232     if (ret != CM_SUCCESS) {
233         return ret;
234     }
235 
236     if (certParam->store == CM_SYS_CREDENTIAL_STORE &&
237         !CmCheckUserIdAndUpdateContext(certParam->userId, &(cmContext->userId))) {
238         CM_LOG_E("input userId is invalid");
239         return CMR_ERROR_INVALID_ARGUMENT;
240     }
241 
242     if (!CmPermissionCheck(certParam->store)) {
243         CM_LOG_E("permission check failed");
244         return CMR_ERROR_PERMISSION_DENIED;
245     }
246 
247     if (!CmIsSystemAppByStoreType(certParam->store)) {
248         CM_LOG_E("install app cert: caller is not system app");
249         return CMR_ERROR_NOT_SYSTEMP_APP;
250     }
251 
252     return CM_SUCCESS;
253 }
254 
checkCallerAndUri(struct CmContext * cmContext,const struct CmBlob * uri,const uint32_t type,bool isCheckUid)255 static int32_t checkCallerAndUri(struct CmContext *cmContext, const struct CmBlob *uri,
256     const uint32_t type, bool isCheckUid)
257 {
258     struct CMUri uriObj;
259     int32_t ret = CertManagerUriDecode(&uriObj, (char *)uri->data);
260     if (ret != CM_SUCCESS) {
261         CM_LOG_E("Failed to decode uri, ret = %d", ret);
262         return ret;
263     }
264 
265     if ((uriObj.object == NULL) || (uriObj.user == NULL) || (uriObj.app == NULL) || (uriObj.type != type)) {
266         CM_LOG_E("uri format is invalid");
267         (void)CertManagerFreeUri(&uriObj);
268         return CMR_ERROR_INVALID_ARGUMENT;
269     }
270 
271     uint32_t userId = (uint32_t)atoi(uriObj.user);
272     uint32_t uid = (uint32_t)atoi(uriObj.app);
273     (void)CertManagerFreeUri(&uriObj);
274     if ((cmContext->userId != 0) && (cmContext->userId != userId)) {
275         CM_LOG_E("caller userid is not producer");
276         return CMR_ERROR_INVALID_ARGUMENT;
277     }
278 
279     if ((isCheckUid) && (cmContext->userId == 0) && (cmContext->uid != uid)) {
280         CM_LOG_E("caller uid is not producer");
281         return CMR_ERROR_INVALID_ARGUMENT;
282     }
283 
284     cmContext->userId = userId;
285     cmContext->uid = uid;
286     return CM_SUCCESS;
287 }
288 
CmServiceUninstallAppCertCheck(struct CmContext * cmContext,const uint32_t store,const struct CmBlob * keyUri)289 int32_t CmServiceUninstallAppCertCheck(struct CmContext *cmContext,
290     const uint32_t store, const struct CmBlob *keyUri)
291 {
292     if (CM_STORE_CHECK(store)) {
293         CM_LOG_E("invalid input arguments store:%u", store);
294         return CMR_ERROR_INVALID_ARGUMENT;
295     }
296 
297     if (CheckUri(keyUri) != CM_SUCCESS) {
298         CM_LOG_E("invalid input arguments");
299         return CMR_ERROR_INVALID_ARGUMENT;
300     }
301 
302     if (!CmPermissionCheck(store)) {
303         CM_LOG_E("permission check failed");
304         return CMR_ERROR_PERMISSION_DENIED;
305     }
306 
307     if (!CmIsSystemAppByStoreType(store)) {
308         CM_LOG_E("uninstall app cert: caller is not system app");
309         return CMR_ERROR_NOT_SYSTEMP_APP;
310     }
311 
312     if (store == CM_SYS_CREDENTIAL_STORE) {
313         return checkCallerAndUri(cmContext, keyUri, CM_URI_TYPE_SYS_KEY, true);
314     }
315 
316     return CM_SUCCESS;
317 }
318 
CmGetSysAppCertListCheck(const struct CmContext * cmContext,const uint32_t store)319 static int32_t CmGetSysAppCertListCheck(const struct CmContext *cmContext, const uint32_t store)
320 {
321     if (cmContext->userId == 0) {
322         CM_LOG_E("get sys app cert list: caller is not hap");
323         return CMR_ERROR_INVALID_ARGUMENT;
324     }
325 
326     if (!CmHasCommonPermission()) {
327         CM_LOG_E("permission check failed");
328         return CMR_ERROR_PERMISSION_DENIED;
329     }
330 
331     if (!CmIsSystemApp()) {
332         CM_LOG_E("get sys app cert list: caller is not system app");
333         return CMR_ERROR_NOT_SYSTEMP_APP;
334     }
335     return CM_SUCCESS;
336 }
337 
CmServiceGetAppCertListCheck(const struct CmContext * cmContext,const uint32_t store)338 int32_t CmServiceGetAppCertListCheck(const struct CmContext *cmContext, const uint32_t store)
339 {
340     if (CM_STORE_CHECK(store)) {
341         CM_LOG_E("invalid input arguments store:%u", store);
342         return CMR_ERROR_INVALID_ARGUMENT;
343     }
344 
345     if (store == CM_SYS_CREDENTIAL_STORE) {
346         return CmGetSysAppCertListCheck(cmContext, store);
347     }
348 
349     if (!CmHasPrivilegedPermission() || !CmHasCommonPermission()) {
350         CM_LOG_E("permission check failed");
351         return CMR_ERROR_PERMISSION_DENIED;
352     }
353 
354     if (!CmIsSystemApp()) {
355         CM_LOG_E("get app cert list: caller is not system app");
356         return CMR_ERROR_NOT_SYSTEMP_APP;
357     }
358 
359     return CM_SUCCESS;
360 }
361 
CmServiceGetCallingAppCertListCheck(const struct CmContext * cmContext,const uint32_t store)362 int32_t CmServiceGetCallingAppCertListCheck(const struct CmContext *cmContext, const uint32_t store)
363 {
364     if (CM_STORE_CHECK(store)) {
365         CM_LOG_E("invalid input arguments store:%u", store);
366         return CMR_ERROR_INVALID_ARGUMENT;
367     }
368 
369     if (store == CM_SYS_CREDENTIAL_STORE) {
370         return CmGetSysAppCertListCheck(cmContext, store);
371     }
372 
373     if (!CmHasCommonPermission()) {
374         CM_LOG_E("permission check failed");
375         return CMR_ERROR_PERMISSION_DENIED;
376     }
377 
378     if (store == CM_PRI_CREDENTIAL_STORE) {
379         return CM_SUCCESS;
380     }
381 
382     if (!CmHasPrivilegedPermission()) {
383         CM_LOG_E("permission check failed");
384         return CMR_ERROR_PERMISSION_DENIED;
385     }
386 
387     if (!CmIsSystemApp()) {
388         CM_LOG_E("get app cert list: caller is not system app");
389         return CMR_ERROR_NOT_SYSTEMP_APP;
390     }
391 
392     return CM_SUCCESS;
393 }
394 
CmServiceGetAppCertCheck(struct CmContext * cmContext,const uint32_t store,const struct CmBlob * keyUri)395 int32_t CmServiceGetAppCertCheck(struct CmContext *cmContext, const uint32_t store, const struct CmBlob *keyUri)
396 {
397     if (CM_STORE_CHECK(store)) {
398         CM_LOG_E("invalid input arguments store:%u", store);
399         return CMR_ERROR_INVALID_ARGUMENT;
400     }
401 
402     if (CheckUri(keyUri) != CM_SUCCESS) {
403         CM_LOG_E("invalid input arguments");
404         return CMR_ERROR_INVALID_ARGUMENT;
405     }
406 
407     if (!CmHasCommonPermission()) {
408         CM_LOG_E("permission check failed");
409         return CMR_ERROR_PERMISSION_DENIED;
410     }
411 
412     if (store == CM_SYS_CREDENTIAL_STORE) {
413         int32_t ret = checkCallerAndUri(cmContext, keyUri, CM_URI_TYPE_SYS_KEY, false);
414         if (ret != CM_SUCCESS) {
415             CM_LOG_E("get type and userid from uri error");
416             return ret;
417         }
418 
419         if (!CmHasSystemAppPermission()) {
420             CM_LOG_E("sys ca store check failed");
421             return CMR_ERROR_PERMISSION_DENIED;
422         }
423         if (!CmIsSystemApp()) {
424             CM_LOG_E("GetAppCertCheck: caller is not system app");
425             return CMR_ERROR_NOT_SYSTEMP_APP;
426         }
427     }
428 
429     return CM_SUCCESS;
430 }
431 
CmCheckAndUpdateCallerUserId(const uint32_t inputUserId,uint32_t * callerUserId)432 static bool CmCheckAndUpdateCallerUserId(const uint32_t inputUserId, uint32_t *callerUserId)
433 {
434     if (*callerUserId == 0) { /* caller is sa */
435         if (inputUserId == INIT_INVALID_VALUE) {
436             CM_LOG_D("caller is sa");
437             return true;
438         }
439         CM_LOG_D("sa designates the userid: update caller userId from %u to %u", *callerUserId, inputUserId);
440         *callerUserId = inputUserId;
441         return true;
442     }
443 
444     /* caller is hap, callerUserId is not 0 */
445     if (inputUserId != INIT_INVALID_VALUE) {
446         CM_LOG_E("caller is hap, input userId %u is not supported", inputUserId);
447         return false;
448     }
449     return true;
450 }
451 
CmServiceInstallUserCertCheck(struct CmContext * cmContext,const struct CmBlob * userCert,const struct CmBlob * certAlias,const uint32_t userId)452 int32_t CmServiceInstallUserCertCheck(struct CmContext *cmContext, const struct CmBlob *userCert,
453     const struct CmBlob *certAlias, const uint32_t userId)
454 {
455     if (cmContext == NULL) {
456         CM_LOG_E("CmServiceInstallUserCertCheck: context is null");
457         return CMR_ERROR_INVALID_ARGUMENT;
458     }
459 
460     if ((CmCheckBlob(userCert) != CM_SUCCESS) || userCert->size > MAX_LEN_CERTIFICATE) {
461         CM_LOG_E("input params userCert is invalid");
462         return CMR_ERROR_INVALID_ARGUMENT;
463     }
464 
465     int32_t ret = CmCheckCertAlias(certAlias, CM_USER_TRUSTED_STORE);
466     if (ret != CM_SUCCESS) {
467         return ret;
468     }
469 
470     if (!CmHasCommonPermission() || !CmHasUserTrustedPermission()) {
471         CM_LOG_E("install user cert: caller no permission");
472         return CMR_ERROR_PERMISSION_DENIED;
473     }
474 
475     if (!CmIsSystemApp()) {
476         CM_LOG_E("install user cert: caller is not system app");
477         return CMR_ERROR_NOT_SYSTEMP_APP;
478     }
479 
480     if (!CmCheckAndUpdateCallerUserId(userId, &(cmContext->userId))) {
481         CM_LOG_E("input userId is invalid");
482         return CMR_ERROR_INVALID_ARGUMENT;
483     }
484     return CM_SUCCESS;
485 }
486 
CmServiceUninstallUserCertCheck(struct CmContext * cmContext,const struct CmBlob * certUri)487 int32_t CmServiceUninstallUserCertCheck(struct CmContext *cmContext, const struct CmBlob *certUri)
488 {
489     if (cmContext == NULL) {
490         CM_LOG_E("CmServiceUninstallUserCertCheck: context is null");
491         return CMR_ERROR_INVALID_ARGUMENT;
492     }
493 
494     if (CmCheckBlob(certUri) != CM_SUCCESS || CheckUri(certUri) != CM_SUCCESS) {
495         CM_LOG_E("certUri is invalid");
496         return CMR_ERROR_INVALID_ARGUMENT;
497     }
498 
499     if (!CmHasCommonPermission() || !CmHasUserTrustedPermission()) {
500         CM_LOG_E("uninstall user cert: caller no permission");
501         return CMR_ERROR_PERMISSION_DENIED;
502     }
503 
504     if (!CmIsSystemApp()) {
505         CM_LOG_E("uninstall user cert: caller is not system app");
506         return CMR_ERROR_NOT_SYSTEMP_APP;
507     }
508 
509     int32_t ret = checkCallerAndUri(cmContext, certUri, CM_URI_TYPE_CERTIFICATE, true);
510     if (ret != CM_SUCCESS) {
511         CM_LOG_E("uninstall user cert: caller and uri check fail");
512         return ret;
513     }
514     return CM_SUCCESS;
515 }
516