1 /*
2  * Copyright (c) 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 "cm_cert_property_rdb.h"
17 
18 #include "securec.h"
19 
20 #include "cm_log.h"
21 #include "cm_rdb_config.h"
22 #include "cm_rdb_data_manager.h"
23 #include "cm_scope_guard.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::Security::CertManager;
27 
28 const std::string CERT_MANAGER_RDB_NAME = "/cert_manager.db";
29 const std::string CERT_PROPERTY_TABLE_NAME = "cert_property";
30 const std::string COLUMN_URI = "URI";
31 const std::string COLUMN_ALIAS = "ALIAS";
32 const std::string COLUMN_SUBJECT_NAME = "SUBJECT_NAME";
33 const std::string COLUMN_CERT_TYPE = "CERT_TYPE";
34 const std::string COLUMN_CERT_STORE = "CERT_STORE";
35 const std::string COLUMN_USERID = "USERID";
36 const std::string COLUMN_UID = "UID";
37 
38 static std::shared_ptr<CmRdbDataManager> cmRdbDataManager = nullptr;
39 
CreateCertPropertyRdb(void)40 int32_t CreateCertPropertyRdb(void)
41 {
42     CM_LOG_D("enter CreateCertPropertyRdb");
43     RdbConfig rdbConfig;
44     rdbConfig.dbName = CERT_MANAGER_RDB_NAME;
45     rdbConfig.tableName = CERT_PROPERTY_TABLE_NAME;
46     rdbConfig.createTableSql = std::string("CREATE TABLE IF NOT EXISTS " + CERT_PROPERTY_TABLE_NAME +
47         "(URI TEXT PRIMARY KEY, ALIAS TEXT NOT NULL, SUBJECT_NAME TEXT NOT NULL, CERT_TYPE TEXT NOT NULL, " +
48         "CERT_STORE INTEGER NOT NULL, USERID INTEGER NOT NULL, UID INTEGER NOT NULL)");
49     cmRdbDataManager = std::make_shared<CmRdbDataManager>(rdbConfig);
50     bool ret = cmRdbDataManager->CreateTable();
51     if (!ret) {
52         CM_LOG_E("Failed to create cert_property table");
53         return CMR_ERROR_CREATE_RDB_TABLE_FAIL;
54     }
55     return CM_SUCCESS;
56 }
57 
InsertCertProperty(const struct CertProperty * certProperty)58 int32_t InsertCertProperty(const struct CertProperty *certProperty)
59 {
60     CM_LOG_D("enter InsertCertProperty");
61     if (certProperty == nullptr) {
62         CM_LOG_E("certProperty is nullptr");
63         return CMR_ERROR_INVALID_ARGUMENT;
64     }
65     if (cmRdbDataManager == nullptr) {
66         CM_LOG_E("cmRdbDataManager is nullptr");
67         return CMR_ERROR_NULL_POINTER;
68     }
69 
70     NativeRdb::ValuesBucket insertBucket;
71     insertBucket.PutString(COLUMN_URI, std::string(certProperty->uri));
72     insertBucket.PutString(COLUMN_ALIAS, std::string(certProperty->alias));
73     insertBucket.PutString(COLUMN_SUBJECT_NAME, std::string(certProperty->subjectName));
74     insertBucket.PutString(COLUMN_CERT_TYPE, std::string(certProperty->certType));
75     insertBucket.PutInt(COLUMN_CERT_STORE, certProperty->certStore);
76     insertBucket.PutInt(COLUMN_USERID, certProperty->userId);
77     insertBucket.PutInt(COLUMN_UID, certProperty->uid);
78     bool ret = cmRdbDataManager->InsertData(insertBucket);
79     if (!ret) {
80         CM_LOG_E("Failed to insert cert:%s property data", certProperty->uri);
81         return CMR_ERROR_INSERT_RDB_DATA_FAIL;
82     }
83     return CM_SUCCESS;
84 }
85 
DeleteCertProperty(const char * uri)86 int32_t DeleteCertProperty(const char *uri)
87 {
88     CM_LOG_D("enter DeleteCertProperty");
89     if (uri == nullptr) {
90         CM_LOG_E("uri is invalid");
91         return CMR_ERROR_INVALID_ARGUMENT;
92     }
93     if (cmRdbDataManager == nullptr) {
94         CM_LOG_E("cmRdbDataManager is nullptr");
95         return CMR_ERROR_NULL_POINTER;
96     }
97 
98     bool ret = cmRdbDataManager->DeleteData(std::string(uri), COLUMN_URI);
99     if (!ret) {
100         CM_LOG_E("Failed to delete cert:%s property data", uri);
101         return CMR_ERROR_DELETE_RDB_DATA_FAIL;
102     }
103     return CM_SUCCESS;
104 }
105 
UpdateCertProperty(const struct CertProperty * certProperty)106 int32_t UpdateCertProperty(const struct CertProperty *certProperty)
107 {
108     CM_LOG_D("enter UpdateCertProperty");
109     if (certProperty == nullptr) {
110         CM_LOG_E("certProperty is nullptr");
111         return CMR_ERROR_INVALID_ARGUMENT;
112     }
113     if (cmRdbDataManager == nullptr) {
114         CM_LOG_E("cmRdbDataManager is nullptr");
115         return CMR_ERROR_NULL_POINTER;
116     }
117 
118     NativeRdb::ValuesBucket updateBucket;
119     updateBucket.PutString(COLUMN_URI, std::string(certProperty->uri));
120     updateBucket.PutString(COLUMN_ALIAS, std::string(certProperty->alias));
121     updateBucket.PutString(COLUMN_SUBJECT_NAME, std::string(certProperty->subjectName));
122     updateBucket.PutString(COLUMN_CERT_TYPE, std::string(certProperty->certType));
123     updateBucket.PutInt(COLUMN_CERT_STORE, certProperty->certStore);
124     updateBucket.PutInt(COLUMN_USERID, certProperty->userId);
125     updateBucket.PutInt(COLUMN_UID, certProperty->uid);
126     bool ret = cmRdbDataManager->UpdateData(std::string(certProperty->uri), COLUMN_URI, updateBucket);
127     if (!ret) {
128         CM_LOG_E("Failed to update cert:%s property data", certProperty->uri);
129         return CMR_ERROR_UPDATE_RDB_DATA_FAIL;
130     }
131     return CM_SUCCESS;
132 }
133 
GetStringValue(const std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet,const std::string & columnName,char * outBuf,uint32_t outBufLen)134 static int32_t GetStringValue(const std::shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet,
135     const std::string &columnName, char *outBuf, uint32_t outBufLen)
136 {
137     int columnIndex = 0;
138     auto ret = resultSet->GetColumnIndex(columnName, columnIndex);
139     if (ret != NativeRdb::E_OK) {
140         CM_LOG_E("Failed to get column index, column: %{public}s", columnName.c_str());
141         return CMR_ERROR_QUERY_RDB_DATA_FAIL;
142     }
143 
144     std::string value;
145     ret = resultSet->GetString(columnIndex, value);
146     if (ret != NativeRdb::E_OK) {
147         CM_LOG_E("Failed to get column value, column: %{public}s", columnName.c_str());
148         return CMR_ERROR_QUERY_RDB_DATA_FAIL;
149     }
150 
151     if (memcpy_s(outBuf, outBufLen, value.c_str(), value.size() + 1) != EOK) {
152         CM_LOG_E("memcpy_s fail");
153         return CMR_ERROR_INVALID_OPERATION;
154     }
155     return CM_SUCCESS;
156 }
157 
GetIntValue(const std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet,const std::string & columnName,int32_t & value)158 static int32_t GetIntValue(const std::shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet,
159     const std::string &columnName, int32_t &value)
160 {
161     int columnIndex = 0;
162     auto ret = resultSet->GetColumnIndex(columnName, columnIndex);
163     if (ret != NativeRdb::E_OK) {
164         CM_LOG_E("Failed to get column index, column: %{public}s", columnName.c_str());
165         return CMR_ERROR_QUERY_RDB_DATA_FAIL;
166     }
167 
168     ret = resultSet->GetInt(columnIndex, value);
169     if (ret != NativeRdb::E_OK) {
170         CM_LOG_E("Failed to get column value, column: %{public}s", columnName.c_str());
171         return CMR_ERROR_QUERY_RDB_DATA_FAIL;
172     }
173     return CM_SUCCESS;
174 }
175 
GetCertProperty(const std::shared_ptr<NativeRdb::AbsSharedResultSet> & resultSet,struct CertProperty * certProperty)176 static int32_t GetCertProperty(const std::shared_ptr<NativeRdb::AbsSharedResultSet> &resultSet,
177     struct CertProperty *certProperty)
178 {
179     int32_t ret = GetStringValue(resultSet, COLUMN_URI, certProperty->uri, MAX_LEN_URI);
180     if (ret != CM_SUCCESS) {
181         CM_LOG_E("Failed to get uri");
182         return ret;
183     }
184 
185     ret = GetStringValue(resultSet, COLUMN_ALIAS, certProperty->alias, MAX_LEN_CERT_ALIAS);
186     if (ret != CM_SUCCESS) {
187         CM_LOG_E("Failed to get alias");
188         return ret;
189     }
190 
191     ret = GetStringValue(resultSet, COLUMN_SUBJECT_NAME, certProperty->subjectName, MAX_LEN_SUBJECT_NAME);
192     if (ret != CM_SUCCESS) {
193         CM_LOG_E("Failed to get subjectName");
194         return ret;
195     }
196 
197     ret = GetStringValue(resultSet, COLUMN_CERT_TYPE, certProperty->certType, MAX_LEN_CERT_TYPE);
198     if (ret != CM_SUCCESS) {
199         CM_LOG_E("Failed to get certType");
200         return ret;
201     }
202 
203     ret = GetIntValue(resultSet, COLUMN_CERT_STORE, certProperty->certStore);
204     if (ret != CM_SUCCESS) {
205         CM_LOG_E("Failed to get certStore");
206         return ret;
207     }
208 
209     ret = GetIntValue(resultSet, COLUMN_USERID, certProperty->userId);
210     if (ret != CM_SUCCESS) {
211         CM_LOG_E("Failed to get userId");
212         return ret;
213     }
214 
215     ret = GetIntValue(resultSet, COLUMN_UID, certProperty->uid);
216     if (ret != CM_SUCCESS) {
217         CM_LOG_E("Failed to get uid");
218         return ret;
219     }
220     return ret;
221 }
222 
QueryCertProperty(const char * uri,struct CertProperty * certProperty)223 int32_t QueryCertProperty(const char *uri, struct CertProperty *certProperty)
224 {
225     CM_LOG_D("enter QueryCertProperty");
226     if (uri == nullptr || certProperty == nullptr) {
227         CM_LOG_E("input param is invalid");
228         return CMR_ERROR_INVALID_ARGUMENT;
229     }
230     if (cmRdbDataManager == nullptr) {
231         CM_LOG_E("cmRdbDataManager is nullptr");
232         return CMR_ERROR_NULL_POINTER;
233     }
234 
235     auto absSharedResultSet = cmRdbDataManager->QueryData(std::string(uri), COLUMN_URI);
236     if (absSharedResultSet == nullptr) {
237         CM_LOG_E("Failed to query cert: %s property data", uri);
238         return CMR_ERROR_QUERY_RDB_DATA_FAIL;
239     }
240 
241     CmScoprGuard stateGuard([&] { absSharedResultSet->Close(); });
242     int rowCount = 0;
243     int ret = absSharedResultSet->GetRowCount(rowCount);
244     if (ret != NativeRdb::E_OK) {
245         CM_LOG_E("Failed to get row count, ret: %d", ret);
246         return CMR_ERROR_QUERY_RDB_DATA_FAIL;
247     }
248     if (rowCount <= 0) {
249         CM_LOG_D("Finish to query, cert: %s does not exist in the database", uri);
250         return CM_SUCCESS;
251     }
252 
253     ret = absSharedResultSet->GoToFirstRow();
254     if (ret != NativeRdb::E_OK) {
255         CM_LOG_E("Failed to go to firstRow, ret: %d", ret);
256         return CMR_ERROR_QUERY_RDB_DATA_FAIL;
257     }
258 
259     int32_t result = GetCertProperty(absSharedResultSet, certProperty);
260     if (result != CM_SUCCESS) {
261         CM_LOG_E("Failed to get cert property data");
262         return CMR_ERROR_QUERY_RDB_DATA_FAIL;
263     }
264     return CM_SUCCESS;
265 }