Switch to sqlcipher library
[platform/core/security/key-manager.git] / src / manager / service / db-crypto.h
1 /*
2  * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        db-crypto.h
18  * @author      Zofia Abramowska (z.abramowska@samsung.com)
19  * @version     1.0
20  * @brief       Header of encrypted db access layer
21  */
22 #ifndef CKM_DB_CRYPTO_H
23 #define CKM_DB_CRYPTO_H
24
25 #include <vector>
26 #include <string>
27
28 #include <dpl/db/sql_connection.h>
29
30 #include <ckm/ckm-type.h>
31 #include <exception.h>
32 #include <db-row.h>
33 #include <permission.h>
34 #include <protocols.h>
35
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
38
39 namespace CKM {
40 namespace DB {
41 class Crypto {
42 public:
43         using RowOptional = boost::optional<Row>;
44         using RawBufferOptional = boost::optional<RawBuffer>;
45
46         Crypto() : m_inUserTransaction(false) {}
47
48         // user name instead of path?
49         // in no way to I condone the use of std::string for legacyPath; see: review
50         Crypto(const std::string &legacyPath, const std::string &path, const RawBuffer &rawPass);
51         Crypto(const Crypto &other) = delete;
52         Crypto(Crypto &&other);
53
54         Crypto &operator=(const Crypto &) = delete;
55         Crypto &operator=(Crypto &&other);
56
57         virtual ~Crypto() = default;
58
59         void saveRow(
60                 const Row &row);
61
62         void saveRows(
63                 const Name &name,
64                 const ClientId &owner,
65                 const RowVector &rows);
66
67         void updateRow(
68                 const Row &row);
69
70         bool isNameOwnerPresent(
71                 const Name &name,
72                 const ClientId &owner) const;
73
74         RowOptional getRow(
75                 const Name &name,
76                 const ClientId &owner,
77                 DataType type);
78
79         RowOptional getRow(
80                 const Name &name,
81                 const ClientId &owner,
82                 DataType typeRangeStart,
83                 DataType typeRangeStop);
84
85         void getRows(
86                 const Name &name,
87                 const ClientId &owner,
88                 DataType type,
89                 RowVector &output);
90
91         void getRows(
92                 const Name &name,
93                 const ClientId &owner,
94                 DataType typeRangeStart,
95                 DataType typeRangeStop,
96                 RowVector &output);
97
98         void listNames(
99                 const ClientId &owner,
100                 OwnerNameVector &ownerNameVector,
101                 DataType type);
102
103         void listNames(
104                 const ClientId &owner,
105                 OwnerNameVector &ownerNameVector,
106                 DataType typeRangeStart,
107                 DataType typeRangeStop);
108
109         bool deleteRow(
110                 const Name &name,
111                 const ClientId &owner);
112
113         // keys
114         void saveKey(const ClientId &owner, const RawBuffer &key);
115         RawBufferOptional getKey(const ClientId &owner);
116         void deleteKey(const ClientId &owner);
117
118         // permissions
119         void setPermission(
120                 const Name &name,
121                 const ClientId &owner,
122                 const ClientId &accessor,
123                 const PermissionMask permissionMask);
124
125         PermissionMaskOptional getPermissionRow(
126                 const Name &name,
127                 const ClientId &owner,
128                 const ClientId &accessor) const;
129
130         // transactions
131         int beginTransaction();
132         int commitTransaction();
133         int rollbackTransaction();
134
135         class Transaction {
136         public:
137                 explicit Transaction(Crypto *db) : m_db(db), m_inTransaction(false)
138                 {
139                         if (!m_db->m_inUserTransaction) {
140                                 try {
141                                         m_db->m_connection->ExecCommand("BEGIN EXCLUSIVE");
142                                         m_db->m_inUserTransaction = true;
143                                         m_inTransaction = true;
144                                 } catch (const SqlConnection::Exception::InternalError &) {
145                                         ThrowErr(Exc::TransactionFailed, "sqlite got into infinite busy state");
146                                 } catch (const SqlConnection::Exception::Base &) {
147                                         ThrowErr(Exc::TransactionFailed, "Couldn't begin transaction");
148                                 }
149                         }
150                 }
151
152                 void commit()
153                 {
154                         if (m_inTransaction) {
155                                 try {
156                                         m_db->m_connection->CommitTransaction();
157                                         m_db->m_inUserTransaction = false;
158                                         m_inTransaction = false;
159                                 } catch (const SqlConnection::Exception::InternalError &) {
160                                         ThrowErr(Exc::TransactionFailed, "sqlite got into infinite busy state");
161                                 } catch (const SqlConnection::Exception::Base &) {
162                                         ThrowErr(Exc::TransactionFailed, "Couldn't commit transaction");
163                                 }
164                         }
165                 }
166
167                 void rollback()
168                 {
169                         if (m_inTransaction) {
170                                 try {
171                                         m_db->m_connection->RollbackTransaction();
172                                         m_db->m_inUserTransaction = false;
173                                         m_inTransaction = false;
174                                 } catch (const SqlConnection::Exception::InternalError &) {
175                                         ThrowErr(Exc::TransactionFailed, "sqlite got into infinite busy state");
176                                 } catch (const SqlConnection::Exception::Base &) {
177                                         ThrowErr(Exc::TransactionFailed, "Couldn't rollback transaction");
178                                 }
179                         }
180                 }
181
182                 ~Transaction()
183                 {
184                         try {
185                                 if (m_inTransaction) {
186                                         m_db->m_inUserTransaction = false;
187                                         m_db->m_connection->RollbackTransaction();
188                                 }
189                         } catch (const SqlConnection::Exception::InternalError &) {
190                                 LogError("sqlite got into infinite busy state");
191                         } catch (const SqlConnection::Exception::Base &) {
192                                 LogError("Transaction rollback failed!");
193                         }
194                 }
195
196         private:
197                 Crypto *m_db;
198                 bool m_inTransaction;
199         };
200
201 protected:
202         std::unique_ptr<SqlConnection> m_connection;
203
204         Row getRow(
205                 const SqlConnection::DataCommandUniquePtr &selectCommand) const;
206
207 private:
208         bool m_inUserTransaction;
209
210         void resetDB();
211         void initDatabase();
212         void createDBSchema();
213         /**
214          * return current database version
215          *
216          * @param[out] schemaVersion    if success, will contain DB schema version code
217          *
218          * @return false on DB empty or corrupted, true if information read
219          */
220         bool getDBVersion(int &schemaVersion);
221
222         using ScriptOptional = boost::optional<std::string>;
223         ScriptOptional getScript(const std::string &scriptName) const;
224         ScriptOptional getMigrationScript(int db_version) const;
225
226         void createTable(
227                 const char *create_cmd,
228                 const char *table_name);
229
230         void createView(
231                 const char *create_cmd);
232
233         class SchemaInfo {
234         public:
235                 explicit SchemaInfo(SqlConnection *connection) : m_connection(connection) {}
236
237                 void setVersionInfo();
238                 bool getVersionInfo(int &version);
239
240         private:
241                 SqlConnection *m_connection;
242         };
243
244 public:
245         class NameTable {
246         public:
247                 explicit NameTable(SqlConnection *connection) : m_connection(connection) {}
248
249                 void addRow(
250                         const Name &name,
251                         const ClientId &owner);
252
253                 void deleteRow(
254                         const Name &name,
255                         const ClientId &owner);
256
257                 void deleteAllRows(
258                         const ClientId &owner);
259
260                 bool isPresent(
261                         const Name &name,
262                         const ClientId &owner) const;
263
264         private:
265                 SqlConnection *m_connection;
266         };
267
268         class ObjectTable {
269         public:
270                 explicit ObjectTable(SqlConnection *connection) : m_connection(connection) {}
271
272                 void addRow(
273                         const Row &row);
274                 void updateRow(
275                         const Row &row);
276
277         private:
278                 SqlConnection *m_connection;
279         };
280
281         class PermissionTable {
282         public:
283                 explicit PermissionTable(SqlConnection *connection) : m_connection(
284                                 connection) {}
285
286                 void setPermission(
287                         const Name &name,
288                         const ClientId &owner,
289                         const ClientId &accessor,
290                         const PermissionMask permissionMask);
291
292                 PermissionMaskOptional getPermissionRow(
293                         const Name &name,
294                         const ClientId &owner,
295                         const ClientId &accessor) const;
296
297         private:
298                 SqlConnection *m_connection;
299         };
300 };
301
302 } // namespace DB
303 } // namespace CKM
304
305 #pragma GCC diagnostic pop
306 #endif // CKM_DB_CRYPTO_H