1 /*
2  * Copyright (c) 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 
16 #include "cm_security_guard_info.h"
17 
18 #include "cm_log.h"
19 #include "cm_mem.h"
20 #include "cm_security_guard_report.h"
21 
22 #ifdef SUPPORT_SECURITY_GUARD
23 #define CM_INVALID_NAME "nameInvalid"
24 #define CM_DELETE_ALL_NAME "deleteAll"
25 #define CM_REPORT_MAX_NAME_LEN 256
26 
IsNameValid(const struct CmBlob * name)27 static bool IsNameValid(const struct CmBlob *name)
28 {
29     if ((CmCheckBlob(name) != CM_SUCCESS) || (name->size >= CM_REPORT_MAX_NAME_LEN)) {
30         return false;
31     }
32 
33     for (uint32_t i = 1; i < name->size; ++i) { /* from index 1 has '\0' */
34         if (name->data[i] == 0) {
35             return true;
36         }
37     }
38     return false;
39 }
40 
41 #define ANONYMOUS_LEN 4
42 
AnonymousName(char * name,uint32_t nameLen)43 static void AnonymousName(char *name, uint32_t nameLen)
44 {
45     char p = '*';
46     uint32_t offset = strlen("o=");
47     char *substr = strstr(name, "o=");
48     if (substr == NULL || strlen(substr) == offset) {
49         if (nameLen <= ANONYMOUS_LEN) {
50             (void)memset_s(name, nameLen, p, nameLen);
51         } else {
52             (void)memset_s(name + nameLen - ANONYMOUS_LEN, ANONYMOUS_LEN, p, ANONYMOUS_LEN);
53         }
54         return;
55     }
56 
57     uint32_t substrLen = strlen(substr);
58     if (substrLen <= ANONYMOUS_LEN + offset) {
59         (void)memset_s(substr + offset, substrLen - offset, p, substrLen - offset);
60     } else {
61         (void)memset_s(substr + offset, ANONYMOUS_LEN, p, ANONYMOUS_LEN);
62     }
63 }
64 
ConstructInfoName(const struct CmBlob * input,char ** name)65 static int32_t ConstructInfoName(const struct CmBlob *input, char **name)
66 {
67     bool isNameValid = IsNameValid(input);
68     uint32_t nameLen = isNameValid ? input->size : strlen(CM_INVALID_NAME) + 1;
69     *name = (char *)CmMalloc(nameLen);
70     if (*name == NULL) {
71         return CMR_ERROR_MALLOC_FAIL;
72     }
73     (void)memset_s(*name, nameLen, 0, nameLen); /* initialized to 0 to avoid that input does not end with '\0' */
74     (void)strcpy_s(*name, nameLen, isNameValid ? (char *)input->data : CM_INVALID_NAME);
75 
76     if (isNameValid) {
77         AnonymousName(*name, nameLen - 1); /* nameLen is bigger than 1 and exclude end '\0' */
78     }
79     return CM_SUCCESS;
80 }
81 
ConstructInfoAndReport(const struct CmBlob * input,const char * action,struct CmReportSGInfo * info)82 static void ConstructInfoAndReport(const struct CmBlob *input, const char *action, struct CmReportSGInfo *info)
83 {
84     if (strcpy_s(info->action, sizeof(info->action), action) != EOK) {
85         return;
86     }
87     if (ConstructInfoName(input, &info->name) != CM_SUCCESS) {
88         return;
89     }
90     CmReportSGRecord(info);
91     CM_FREE_PTR(info->name);
92 }
93 #endif
94 
CmReportSGSetCertStatus(const struct CmBlob * certUri,uint32_t store,uint32_t status,int32_t result)95 void CmReportSGSetCertStatus(const struct CmBlob *certUri, uint32_t store, uint32_t status, int32_t result)
96 {
97 #ifdef SUPPORT_SECURITY_GUARD
98     struct CmReportSGInfo info;
99     (void)memset_s(&info, sizeof(info), 0, sizeof(info));
100 
101     info.result = result;
102     info.uid = CmGetCallingUid();
103     info.isSetGrantUid = false;
104     info.isSetStatus = true;
105     info.status = (status == 0) ? true : false; /* 0 indicates the certificate enabled status */
106 
107     char *action = (store == CM_SYSTEM_TRUSTED_STORE) ? "CmSetSystemCertStatus" : "CmSetUserCertStatus";
108     ConstructInfoAndReport(certUri, action, &info);
109 #else
110     (void)certUri;
111     (void)store;
112     (void)status;
113     (void)result;
114 #endif
115 }
116 
CmReportSGInstallUserCert(const struct CmBlob * certAlias,int32_t result)117 void CmReportSGInstallUserCert(const struct CmBlob *certAlias, int32_t result)
118 {
119 #ifdef SUPPORT_SECURITY_GUARD
120     struct CmReportSGInfo info;
121     (void)memset_s(&info, sizeof(info), 0, sizeof(info));
122 
123     info.result = result;
124     info.uid = CmGetCallingUid();
125     info.isSetGrantUid = false;
126     info.isSetStatus = false;
127 
128     char *action = "CmInstallUserCert";
129     ConstructInfoAndReport(certAlias, action, &info);
130 #else
131     (void)certAlias;
132     (void)result;
133 #endif
134 }
135 
CmReportSGUninstallUserCert(const struct CmBlob * certUri,bool isUninstallAll,int32_t result)136 void CmReportSGUninstallUserCert(const struct CmBlob *certUri, bool isUninstallAll, int32_t result)
137 {
138 #ifdef SUPPORT_SECURITY_GUARD
139     struct CmReportSGInfo info;
140     (void)memset_s(&info, sizeof(info), 0, sizeof(info));
141 
142     info.result = result;
143     info.uid = CmGetCallingUid();
144     info.isSetGrantUid = false;
145     info.isSetStatus = false;
146 
147     if (isUninstallAll) {
148         if (strcpy_s(info.action, sizeof(info.action), "CmUninstallAllUserCert") != EOK) {
149             return;
150         }
151         info.name = CM_DELETE_ALL_NAME;
152         return CmReportSGRecord(&info);
153     }
154 
155     char *action = "CmUninstallUserCert";
156     ConstructInfoAndReport(certUri, action, &info);
157 #else
158     (void)certUri;
159     (void)isUninstallAll;
160     (void)result;
161 #endif
162 }
163 
CmReportSGInstallAppCert(const struct CmBlob * certAlias,uint32_t store,int32_t result)164 void CmReportSGInstallAppCert(const struct CmBlob *certAlias, uint32_t store, int32_t result)
165 {
166 #ifdef SUPPORT_SECURITY_GUARD
167     struct CmReportSGInfo info;
168     (void)memset_s(&info, sizeof(info), 0, sizeof(info));
169 
170     info.result = result;
171     info.uid = CmGetCallingUid();
172     info.isSetGrantUid = false;
173     info.isSetStatus = false;
174 
175     char *action = (store == CM_CREDENTIAL_STORE) ? "CmInstallAppCert" : "CmInstallPriAppCert";
176     ConstructInfoAndReport(certAlias, action, &info);
177 #else
178     (void)certAlias;
179     (void)store;
180     (void)result;
181 #endif
182 }
183 
CmReportSGUninstallAppCert(const struct CmBlob * keyUri,uint32_t store,bool isUninstallAll,int32_t result)184 void CmReportSGUninstallAppCert(const struct CmBlob *keyUri, uint32_t store, bool isUninstallAll, int32_t result)
185 {
186 #ifdef SUPPORT_SECURITY_GUARD
187     struct CmReportSGInfo info;
188     (void)memset_s(&info, sizeof(info), 0, sizeof(info));
189 
190     info.result = result;
191     info.uid = CmGetCallingUid();
192     info.isSetGrantUid = false;
193     info.isSetStatus = false;
194 
195     if (isUninstallAll) {
196         if (strcpy_s(info.action, sizeof(info.action), "CmUninstallAllAppCert") != EOK) {
197             return;
198         }
199         info.name = CM_DELETE_ALL_NAME;
200         return CmReportSGRecord(&info);
201     }
202 
203     char *action = (store == CM_CREDENTIAL_STORE) ? "CmUninstallAppCert" : "CmUninstallPriAppCert";
204     ConstructInfoAndReport(keyUri, action, &info);
205 #else
206     (void)keyUri;
207     (void)store;
208     (void)isUninstallAll;
209     (void)result;
210 #endif
211 }
212 
CmReportSGGrantAppCert(const struct CmBlob * keyUri,uint32_t appUid,bool isRemove,int32_t result)213 void CmReportSGGrantAppCert(const struct CmBlob *keyUri, uint32_t appUid, bool isRemove, int32_t result)
214 {
215 #ifdef SUPPORT_SECURITY_GUARD
216     struct CmReportSGInfo info;
217     (void)memset_s(&info, sizeof(info), 0, sizeof(info));
218 
219     info.result = result;
220     info.uid = CmGetCallingUid();
221     info.isSetStatus = false;
222     info.isSetGrantUid = true;
223     info.grantUid = appUid;
224 
225     char *action = isRemove ? "CmRemoveGrantedAppUid" : "CmGrantAppCert";
226     ConstructInfoAndReport(keyUri, action, &info);
227 #else
228     (void)keyUri;
229     (void)appUid;
230     (void)isRemove;
231     (void)result;
232 #endif
233 }
234