Alias is not unique user-wide: (alias, label) pair is unique now.
[platform/core/security/key-manager.git] / src / manager / service / db-crypto.cpp
1 /*
2  * Copyright (c) 2014 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.cpp
18  * @author      Zofia Abramowska (z.abramowska@samsung.com)
19  * @version     1.0
20  * @brief       Implementation of encrypted db access layer
21  */
22
23 #include <db-crypto.h>
24 #include <dpl/db/sql_connection.h>
25 #include <dpl/log/log.h>
26 #include <ckm/ckm-error.h>
27
28 #pragma GCC diagnostic push
29 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
30
31 namespace {
32     const char *main_table = "CKM_TABLE";
33     const char *key_table = "KEY_TABLE";
34     const char *permission_table = "PERMISSION_TABLE";
35
36 // CKM_TABLE (alias TEXT, label TEXT, restricted INT, exportable INT, dataType INT, algorithmType INT,
37 //            encryptionScheme INT, iv BLOB, dataSize INT, data BLOB, tag BLOB, idx INT )
38
39     const char *db_create_main_cmd =
40             "CREATE TABLE CKM_TABLE("
41             "   alias TEXT NOT NULL,"
42             "   label TEXT NOT NULL,"
43             "   exportable INTEGER NOT NULL,"
44             "   dataType INTEGER NOT NULL,"
45             "   algorithmType INTEGER NOT NULL,"
46             "   encryptionScheme INTEGER NOT NULL,"
47             "   iv BLOB NOT NULL,"
48             "   dataSize INTEGER NOT NULL,"
49             "   data BLOB NOT NULL,"
50             "   tag BLOB NOT NULL,"
51             "   idx INTEGER PRIMARY KEY AUTOINCREMENT,"
52             "   UNIQUE(alias, label)"
53             "); CREATE INDEX ckm_index_label ON CKM_TABLE(label);"; // based on ANALYZE and performance test result
54
55     const char *insert_main_cmd =
56             "INSERT INTO CKM_TABLE("
57             //      1   2       3
58             "   alias, label, exportable,"
59             //      4           5           6
60             "   dataType, algorithmType, encryptionScheme,"
61             //  7       8       9    10
62             "   iv, dataSize, data, tag) "
63             "VALUES("
64             "   ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);";
65
66     const char *select_alias_cmd =
67             //                                   1              2
68             "SELECT * FROM CKM_TABLE WHERE alias=? AND dataType=?; ";
69
70     const char *select_check_alias_cmd =
71             //                                          1
72             "SELECT dataType FROM CKM_TABLE WHERE alias=?;";
73
74     const char *select_label_global_alias_cmd =
75             //                                       1
76             "SELECT label FROM CKM_TABLE WHERE alias=?;";
77
78     const char *select_label_index_global_alias_cmd =
79             //                                       1
80             "SELECT label, idx FROM CKM_TABLE WHERE alias=?;";
81
82     const char *select_key_alias_cmd =
83             //                                   1
84             "SELECT * FROM CKM_TABLE WHERE alias=?"
85             //                     2     3
86             " AND dataType BETWEEN ? AND ?;";
87
88     const char *delete_alias_cmd =
89             //                                 1
90             "DELETE FROM CKM_TABLE WHERE alias=?;";
91
92     const char *delete_data_with_key_cmd =
93             //                                 1
94             "DELETE FROM CKM_TABLE WHERE label=?;";
95
96 // KEY_TABLE (label TEXT, key BLOB)
97
98     const char *db_create_key_cmd =
99             "CREATE TABLE KEY_TABLE("
100             "   label TEXT PRIMARY KEY,"
101             "   key BLOB NOT NULL"
102             ");";
103
104     const char *insert_key_cmd =
105             "INSERT INTO KEY_TABLE(label, key) VALUES (?, ?);";
106     const char *select_key_cmd =
107             "SELECT key FROM KEY_TABLE WHERE label=?;";
108     const char *delete_key_cmd =
109             "DELETE FROM KEY_TABLE WHERE label=?";
110
111
112 // PERMISSION_TABLE (alias TEXT, label TEXT, access_flags TEXT, idx INT)
113
114     const char *db_create_permission_cmd =
115             "CREATE TABLE PERMISSION_TABLE("
116             "   alias TEXT NOT NULL,"
117             "   label TEXT NOT NULL,"
118             "   accessFlags TEXT NOT NULL,"
119             "   idx INTEGER NOT NULL,"
120             "   FOREIGN KEY(idx) REFERENCES CKM_TABLE(idx) ON DELETE CASCADE,"
121             "   PRIMARY KEY(alias, label)"
122             "); CREATE INDEX perm_index_idx ON PERMISSION_TABLE(idx);"; // based on ANALYZE and performance test result
123
124     const char *set_permission_alias_cmd =
125             "REPLACE INTO PERMISSION_TABLE(alias, label, accessFlags, idx) VALUES (?, ?, ?, ?);";
126
127     const char *select_permission_cmd =
128             //                                                    1           2
129             "SELECT accessFlags FROM PERMISSION_TABLE WHERE alias=? AND label=?;";
130
131     const char *delete_permission_cmd =
132             //                                        1           2
133             "DELETE FROM PERMISSION_TABLE WHERE alias=? AND label=?;";
134
135
136 // CKM_TABLE x PERMISSION_TABLE
137
138     const char *select_type_cross_cmd =
139             //                                                                                                        1              2             3
140             "SELECT C.label, C.alias FROM CKM_TABLE AS C LEFT JOIN PERMISSION_TABLE AS P ON C.alias = P.alias WHERE C.dataType=? AND (C.label=? OR (P.label=? AND P.accessFlags IS NOT NULL)) GROUP BY C.alias;";
141
142     const char *select_key_type_cross_cmd =
143             //                                                                                                       1                 2              3             4
144             "SELECT C.label, C.alias FROM CKM_TABLE AS C LEFT JOIN PERMISSION_TABLE AS P ON C.alias=P.alias WHERE C.dataType>=? AND C.dataType<=? AND (C.label=? OR (P.label=? AND P.accessFlags IS NOT NULL)) GROUP BY C.alias;";
145 }
146
147 namespace CKM {
148 using namespace DB;
149     DBCrypto::DBCrypto(const std::string& path,
150                          const RawBuffer &rawPass) {
151         m_connection = NULL;
152         m_inUserTransaction = false;
153         Try {
154             m_connection = new SqlConnection(path, SqlConnection::Flag::Option::CRW);
155             m_connection->SetKey(rawPass);
156             m_connection->ExecCommand("VACUUM;");
157             initDatabase();
158         } Catch(SqlConnection::Exception::ConnectionBroken) {
159             LogError("Couldn't connect to database: " << path);
160             ReThrow(DBCrypto::Exception::InternalError);
161         } Catch(SqlConnection::Exception::InvalidArguments) {
162             LogError("Couldn't set the key for database");
163             ReThrow(DBCrypto::Exception::InternalError);
164         } Catch(SqlConnection::Exception::SyntaxError) {
165             LogError("Couldn't initiate the database");
166             ReThrow(DBCrypto::Exception::InternalError);
167         } Catch(SqlConnection::Exception::InternalError) {
168             LogError("Couldn't create the database");
169             ReThrow(DBCrypto::Exception::InternalError);
170         }
171     }
172
173     DBCrypto::DBCrypto(DBCrypto &&other) :
174             m_connection(other.m_connection),
175             m_inUserTransaction(other.m_inUserTransaction){
176         other.m_connection = NULL;
177         other.m_inUserTransaction = false;
178     }
179
180     DBCrypto::~DBCrypto() {
181         delete m_connection;
182     }
183
184     DBCrypto& DBCrypto::operator=(DBCrypto&& other) {
185         if (this == &other)
186             return *this;
187         delete m_connection;
188
189         m_connection = other.m_connection;
190         other.m_connection = NULL;
191
192         m_inUserTransaction = other.m_inUserTransaction;
193         other.m_inUserTransaction = false;
194
195         return *this;
196     }
197
198     void DBCrypto::createTable(
199             const char* create_cmd,
200             const char *table_name)
201     {
202         Try {
203             m_connection->ExecCommand(create_cmd);
204         } Catch(SqlConnection::Exception::SyntaxError) {
205             LogError("Couldn't create table : " << table_name << "!");
206             throw;
207         } Catch(SqlConnection::Exception::InternalError) {
208             LogError("Sqlite got into infinite busy state");
209             throw;
210         }
211     }
212
213     void DBCrypto::initDatabase() {
214         Transaction transaction(this);
215         if(!m_connection->CheckTableExist(main_table)) {
216             createTable(db_create_main_cmd, main_table);
217         }
218         if(!m_connection->CheckTableExist(key_table)) {
219             createTable(db_create_key_cmd, key_table);
220         }
221         if(!m_connection->CheckTableExist(permission_table)) {
222             createTable(db_create_permission_cmd, permission_table);
223         }
224         transaction.commit();
225     }
226
227     void DBCrypto::getLabelForAlias(const std::string& alias, std::string & label) const {
228         SqlConnection::DataCommandUniquePtr checkCmd =
229                 m_connection->PrepareDataCommand(select_label_global_alias_cmd);
230         checkCmd->BindString(1, alias.c_str());
231         if(checkCmd->Step()) {
232             label = checkCmd->GetColumnString(0);
233         } else
234             label.clear();
235     }
236
237     void DBCrypto::getLabelForAlias(const std::string& alias, std::string & label, int & index) const
238     {
239         SqlConnection::DataCommandUniquePtr checkCmd =
240                 m_connection->PrepareDataCommand(select_label_index_global_alias_cmd);
241         checkCmd->BindString(1, alias.c_str());
242         if(checkCmd->Step()) {
243             label = checkCmd->GetColumnString(0);
244             index = checkCmd->GetColumnInteger(1);
245         }
246         else
247         {
248             label.clear();
249             index = -1;
250         }
251     }
252
253     bool DBCrypto::checkGlobalAliasExist(const std::string& alias) const {
254         std::string label;
255         getLabelForAlias(alias, label);
256         if(label.empty() == false) {
257             LogDebug("Global alias '" << alias  << "' exists already for label " << label);
258             return true;
259         } else
260             return false;
261     }
262
263     bool DBCrypto::checkAliasExist(const std::string& alias) const {
264         SqlConnection::DataCommandUniquePtr checkCmd =
265                 m_connection->PrepareDataCommand(select_check_alias_cmd);
266         checkCmd->BindString(1, alias.c_str());
267         if(checkCmd->Step()) {
268             LogDebug("Private alias '" << alias  << "' exists already for type "
269                     << checkCmd->GetColumnInteger(0));
270             return true;
271         } else
272             return false;
273     }
274
275     void DBCrypto::saveDBRow(const DBRow &row){
276         Try {
277
278             //Sqlite does not support partial index in our version,
279             //so we do it by hand
280             Transaction transaction(this);
281             if(checkAliasExist(row.alias)) {
282                 ThrowMsg(DBCrypto::Exception::AliasExists,
283                         "Alias exists for alias: " << row.alias);
284             }
285
286             SqlConnection::DataCommandUniquePtr insertCommand =
287                     m_connection->PrepareDataCommand(insert_main_cmd);
288             insertCommand->BindString(1, row.alias.c_str());
289             insertCommand->BindString(2, row.smackLabel.c_str());
290             insertCommand->BindInteger(3, row.exportable);
291             insertCommand->BindInteger(4, static_cast<int>(row.dataType));
292             insertCommand->BindInteger(5, static_cast<int>(row.algorithmType));
293             insertCommand->BindInteger(6, row.encryptionScheme);
294             insertCommand->BindBlob(7, row.iv);
295             insertCommand->BindInteger(8, row.dataSize);
296             insertCommand->BindBlob(9, row.data);
297             insertCommand->BindBlob(10, row.tag);
298
299             insertCommand->Step();
300             transaction.commit();
301             return;
302
303         } Catch(SqlConnection::Exception::SyntaxError) {
304             LogError("Couldn't prepare insert statement");
305         } Catch(SqlConnection::Exception::InternalError) {
306             LogError("Couldn't execute insert statement");
307         }
308         ThrowMsg(DBCrypto::Exception::InternalError,
309                 "Couldn't save DBRow");
310     }
311
312     DBRow DBCrypto::getRow(const SqlConnection::DataCommandUniquePtr &selectCommand) {
313         DBRow row;
314         row.alias = selectCommand->GetColumnString(0);
315         row.smackLabel = selectCommand->GetColumnString(1);
316         row.exportable = selectCommand->GetColumnInteger(2);
317         row.dataType = static_cast<DBDataType>(selectCommand->GetColumnInteger(3));
318         row.algorithmType = static_cast<DBCMAlgType>(selectCommand->GetColumnInteger(4));
319         row.encryptionScheme = selectCommand->GetColumnInteger(5);
320         row.iv = selectCommand->GetColumnBlob(6);
321         row.dataSize = selectCommand->GetColumnInteger(7);
322         row.data = selectCommand->GetColumnBlob(8);
323         row.tag = selectCommand->GetColumnBlob(9);
324         return row;
325     }
326
327     std::string DBCrypto::getPermissionsForAliasAndLabel(const Alias &alias, const std::string &label) const
328     {
329         Try{
330             SqlConnection::DataCommandUniquePtr selectCommand =
331                             m_connection->PrepareDataCommand(select_permission_cmd);
332             selectCommand->BindString(1, alias.c_str());
333             selectCommand->BindString(2, label.c_str());
334
335             if(selectCommand->Step())
336                 return selectCommand->GetColumnString(0);
337
338             return std::string();
339         } Catch (SqlConnection::Exception::InvalidColumn) {
340             LogError("Select statement invalid column error");
341         } Catch (SqlConnection::Exception::SyntaxError) {
342             LogError("Couldn't prepare select statement");
343         } Catch (SqlConnection::Exception::InternalError) {
344             LogError("Couldn't execute select statement");
345         }
346         return std::string();
347     }
348
349
350     bool    DBCrypto::rowAccessControlCheck(const Alias &alias,
351                                             const std::string &owner_label,
352                                             const std::string &clnt_label,
353                                             DBCrypto::DBOperationType access_type) const
354     {
355         // owner of the entry have all the permissions by default
356         // check if requesting client is the entry owner - if so, exit (permission granted)
357         if(owner_label == clnt_label)
358             return true;
359
360         // perform permissions DB query
361         std::string permission_string = this->getPermissionsForAliasAndLabel(alias, clnt_label);
362
363         // check if requested operation is in the permission string
364         LogDebug("pair <" << alias << "," << clnt_label << "> permission rights: \"" << permission_string << "\"");
365         if(permission_string.find(access_type) != std::string::npos)
366             return true;
367
368         return false;
369     }
370     bool    DBCrypto::rowAccessControlCheck(const DBRow & input_row,
371                                             const std::string &clnt_label,
372                                             DBCrypto::DBOperationType access_type) const
373     {
374         return this->rowAccessControlCheck(input_row.alias, input_row.smackLabel, clnt_label, access_type);
375     }
376
377
378     DBCrypto::DBRowOptional DBCrypto::getDBRow(
379         const Alias &alias,
380         const std::string &clnt_label,
381         DBDataType type)
382     {
383         Try {
384             Transaction transaction(this);
385             SqlConnection::DataCommandUniquePtr selectCommand =
386                     m_connection->PrepareDataCommand(select_alias_cmd);
387             selectCommand->BindString(1, alias.c_str());
388             selectCommand->BindInteger(2, static_cast<int>(type));
389
390             if(selectCommand->Step())
391             {
392                 // extract data
393                 DBRow current_row = getRow(selectCommand);
394
395                 // check access rights here
396                 if( ! this->rowAccessControlCheck(current_row, clnt_label, DBCrypto::DB_OPERATION_READ) )
397                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested operation");
398
399                 // finalize DB operations
400                 transaction.commit();
401
402                 // all okay, proceed
403                 return DBRowOptional(current_row);
404             } else {
405                 return DBRowOptional();
406             }
407         } Catch (SqlConnection::Exception::InvalidColumn) {
408             LogError("Select statement invalid column error");
409         } Catch (SqlConnection::Exception::SyntaxError) {
410             LogError("Couldn't prepare select statement");
411         } Catch (SqlConnection::Exception::InternalError) {
412             LogError("Couldn't execute select statement");
413         }
414         ThrowMsg(DBCrypto::Exception::InternalError,
415                 "Couldn't get row for type " << static_cast<int>(type) <<
416                 " alias " << alias << " using client label " << clnt_label);
417     }
418
419     DBCrypto::DBRowOptional DBCrypto::getKeyDBRow(
420         const Alias &alias,
421         const std::string &clnt_label)
422     {
423         Try{
424             Transaction transaction(this);
425             SqlConnection::DataCommandUniquePtr selectCommand =
426                     m_connection->PrepareDataCommand(select_key_alias_cmd);
427             selectCommand->BindString(1, alias.c_str());
428             selectCommand->BindInteger(2, static_cast<int>(DBDataType::DB_KEY_FIRST));
429             selectCommand->BindInteger(3, static_cast<int>(DBDataType::DB_KEY_LAST));
430
431             if(selectCommand->Step())
432             {
433                 // extract data
434                 DBRow current_row = getRow(selectCommand);
435
436                 // check access rights here
437                 if( ! this->rowAccessControlCheck(current_row, clnt_label, DBCrypto::DB_OPERATION_READ) )
438                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested operation");
439
440                 // finalize DB operations
441                 transaction.commit();
442
443                 // all okay, proceed
444                 return DBRowOptional(current_row);
445             } else {
446                 return DBRowOptional();
447             }
448         } Catch (SqlConnection::Exception::InvalidColumn) {
449             LogError("Select statement invalid column error");
450         } Catch (SqlConnection::Exception::SyntaxError) {
451             LogError("Couldn't prepare select statement");
452         } Catch (SqlConnection::Exception::InternalError) {
453             LogError("Couldn't execute select statement");
454         }
455         ThrowMsg(DBCrypto::Exception::InternalError,
456                 "Couldn't get Key for alias " << alias
457                 << " using client label " << clnt_label);
458     }
459
460     void DBCrypto::getSingleType(
461             const std::string &clnt_label,
462             DBDataType type,
463             LabelAliasVector& aliases) const
464     {
465         Try{
466             SqlConnection::DataCommandUniquePtr selectCommand =
467                             m_connection->PrepareDataCommand(select_type_cross_cmd);
468             selectCommand->BindInteger(1, static_cast<int>(type));
469             selectCommand->BindString(2, clnt_label.c_str());
470             selectCommand->BindString(3, clnt_label.c_str());
471
472             while(selectCommand->Step()) {
473                 std::string label = selectCommand->GetColumnString(0);
474                 Alias alias = selectCommand->GetColumnString(1);
475                 aliases.push_back(std::make_pair(label, alias));
476             }
477             return;
478         } Catch (SqlConnection::Exception::InvalidColumn) {
479             LogError("Select statement invalid column error");
480         } Catch (SqlConnection::Exception::SyntaxError) {
481             LogError("Couldn't prepare select statement");
482         } Catch (SqlConnection::Exception::InternalError) {
483             LogError("Couldn't execute select statement");
484         }
485         ThrowMsg(DBCrypto::Exception::InternalError,
486                 "Couldn't get type " << static_cast<int>(type));
487     }
488
489     void DBCrypto::getAliases(
490         const std::string &clnt_label,
491         DBDataType type,
492         LabelAliasVector& aliases)
493     {
494         getSingleType(clnt_label, type, aliases);
495     }
496
497
498     void DBCrypto::getKeyAliases(const std::string &clnt_label, LabelAliasVector &aliases)
499     {
500         Try{
501             Transaction transaction(this);
502             SqlConnection::DataCommandUniquePtr selectCommand =
503                             m_connection->PrepareDataCommand(select_key_type_cross_cmd);
504             selectCommand->BindInteger(1, static_cast<int>(DBDataType::DB_KEY_FIRST));
505             selectCommand->BindInteger(2, static_cast<int>(DBDataType::DB_KEY_LAST));
506             selectCommand->BindString(3, clnt_label.c_str());
507             selectCommand->BindString(4, clnt_label.c_str());
508
509             while(selectCommand->Step()) {
510                 std::string label = selectCommand->GetColumnString(0);
511                 Alias alias = selectCommand->GetColumnString(1);
512                 aliases.push_back(std::make_pair(label, alias));
513             }
514             transaction.commit();
515             return;
516         } Catch (SqlConnection::Exception::InvalidColumn) {
517             LogError("Select statement invalid column error");
518         } Catch (SqlConnection::Exception::SyntaxError) {
519             LogError("Couldn't prepare select statement");
520         } Catch (SqlConnection::Exception::InternalError) {
521             LogError("Couldn't execute select statement");
522         }
523         ThrowMsg(DBCrypto::Exception::InternalError, "Couldn't get key aliases");
524     }
525
526     bool DBCrypto::deleteDBRow(const Alias &alias, const std::string &clnt_label)
527     {
528         Try {
529             Transaction transaction(this);
530
531             std::string owner_label;
532             getLabelForAlias(alias, owner_label);
533             if( ! owner_label.empty() )
534             {
535                 // check access rights here
536                 if( ! this->rowAccessControlCheck(alias, owner_label, clnt_label, DBCrypto::DB_OPERATION_REMOVE) )
537                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested remove operation");
538
539                 // if here, access right is granted - proceed with removal
540                 // note: PERMISSION_TABLE entry will be deleted automatically by SQL (cascade relation between tables)
541                 SqlConnection::DataCommandUniquePtr deleteCommand =
542                         m_connection->PrepareDataCommand(delete_alias_cmd);
543                 deleteCommand->BindString(1, alias.c_str());
544                 deleteCommand->Step();
545
546                 transaction.commit();
547                 return true;
548             }
549             else
550             {
551                 LogError("Error: no such alias: " << alias);
552                 return false;
553             }
554         } Catch (SqlConnection::Exception::SyntaxError) {
555             LogError("Couldn't prepare delete statement");
556         } Catch (SqlConnection::Exception::InternalError) {
557             LogError("Couldn't execute delete statement");
558         }
559         ThrowMsg(DBCrypto::Exception::InternalError,
560                 "Couldn't delete DBRow for alias " << alias << " using client label " << clnt_label);
561     }
562
563     void DBCrypto::saveKey(
564             const std::string& label,
565             const RawBuffer &key)
566     {
567         Try {
568             Transaction transaction(this);
569             SqlConnection::DataCommandUniquePtr insertCommand =
570                     m_connection->PrepareDataCommand(insert_key_cmd);
571             insertCommand->BindString(1, label.c_str());
572             insertCommand->BindBlob(2, key);
573             insertCommand->Step();
574             transaction.commit();
575             return;
576         } Catch (SqlConnection::Exception::SyntaxError) {
577             LogError("Couldn't prepare insert key statement");
578         } Catch (SqlConnection::Exception::InternalError) {
579             LogError("Couldn't execute insert statement");
580         }
581         ThrowMsg(DBCrypto::Exception::InternalError,
582                 "Couldn't save key for label " << label);
583     }
584
585     DBCrypto::RawBufferOptional DBCrypto::getKey(
586             const std::string& label)
587     {
588         Try {
589             Transaction transaction(this);
590             SqlConnection::DataCommandUniquePtr selectCommand =
591                     m_connection->PrepareDataCommand(select_key_cmd);
592             selectCommand->BindString(1, label.c_str());
593
594             if (selectCommand->Step()) {
595                 transaction.commit();
596                 return RawBufferOptional(
597                         selectCommand->GetColumnBlob(0));
598             } else {
599                 transaction.commit();
600                 return RawBufferOptional();
601             }
602
603         } Catch (SqlConnection::Exception::InvalidColumn) {
604             LogError("Select statement invalid column error");
605         } Catch (SqlConnection::Exception::SyntaxError) {
606             LogError("Couldn't prepare insert key statement");
607         } Catch (SqlConnection::Exception::InternalError) {
608             LogError("Couldn't execute insert statement");
609         }
610         ThrowMsg(DBCrypto::Exception::InternalError,
611                 "Couldn't get key for label " << label);
612     }
613
614     void DBCrypto::deleteKey(const std::string& label) {
615         Try {
616             Transaction transaction(this);
617
618             SqlConnection::DataCommandUniquePtr deleteCommand =
619                     m_connection->PrepareDataCommand(delete_key_cmd);
620             deleteCommand->BindString(1, label.c_str());
621             deleteCommand->Step();
622
623             SqlConnection::DataCommandUniquePtr deleteData =
624                 m_connection->PrepareDataCommand(delete_data_with_key_cmd);
625             deleteData->BindString(1, label.c_str());
626             deleteData->Step();
627
628             transaction.commit();
629             return;
630         } Catch (SqlConnection::Exception::SyntaxError) {
631             LogError("Couldn't prepare insert key statement");
632         } Catch (SqlConnection::Exception::InternalError) {
633             LogError("Couldn't execute insert statement");
634         }
635         ThrowMsg(DBCrypto::Exception::InternalError,
636                 "Couldn't delete key for label " << label);
637     }
638
639
640     int DBCrypto::setAccessRights(  const std::string& clnt_label,
641                                     const Alias& alias,
642                                     const std::string& accessor_label,
643                                     const AccessRight value_to_set)
644     {
645         Try {
646             Transaction transaction(this);
647
648             // check if label is present
649             int ckm_tab_index;
650             std::string owner_label;
651             getLabelForAlias(alias, owner_label, ckm_tab_index);
652             if( ! owner_label.empty() )
653             {
654                 // owner can not add permissions to itself
655                 if(owner_label.compare(accessor_label) == 0)
656                     ThrowMsg(Exception::InvalidArgs, "Invalid accessor label: equal to owner label");
657
658                 // check access rights here - only owner can modify permissions
659                 if(owner_label != clnt_label)
660                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested write operation");
661
662                 // if here, access right is granted - proceed to set permissions
663                 SqlConnection::DataCommandUniquePtr setPermissionCommand =
664                         m_connection->PrepareDataCommand(set_permission_alias_cmd);
665                 setPermissionCommand->BindString(1, alias.c_str());
666                 setPermissionCommand->BindString(2, accessor_label.c_str());
667                 setPermissionCommand->BindString(3, toDBAccessRight(value_to_set));
668                 setPermissionCommand->BindInteger(4, ckm_tab_index);
669                 setPermissionCommand->Step();
670                 transaction.commit();
671                 return CKM_API_SUCCESS;
672             }
673             else
674             {
675                 LogError("Error: no such alias: " << alias);
676                 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
677             }
678         } Catch (SqlConnection::Exception::SyntaxError) {
679             LogError("Couldn't prepare set statement");
680         } Catch (SqlConnection::Exception::InternalError) {
681             LogError("Couldn't execute set statement");
682         }
683         ThrowMsg(DBCrypto::Exception::InternalError,
684                 "Couldn't set permissions for alias " << alias << " using client label " << clnt_label);
685     }
686
687     int DBCrypto::clearAccessRights(const std::string& clnt_label,
688                                     const Alias& alias,
689                                     const std::string& accessor_label)
690     {
691         Try {
692             Transaction transaction(this);
693
694             std::string owner_label;
695             getLabelForAlias(alias, owner_label);
696             if( ! owner_label.empty() )
697             {
698                 // check access rights here - only owner can modify permissions
699                 if(owner_label != clnt_label)
700                     ThrowMsg(Exception::PermissionDenied, "Not enough permissions to perform requested write operation");
701
702                 // check if permission for <label, accessor_label> is defined - otherwise nothing to drop
703                 if( this->getPermissionsForAliasAndLabel(alias, accessor_label).empty() )
704                     ThrowMsg(Exception::InvalidArgs, "Permission not found");
705
706                 // if here, access right is granted - proceed to delete permissions
707                 SqlConnection::DataCommandUniquePtr deletePermissionCommand =
708                         m_connection->PrepareDataCommand(delete_permission_cmd);
709                 deletePermissionCommand->BindString(1, alias.c_str());
710                 deletePermissionCommand->BindString(2, accessor_label.c_str());
711                 deletePermissionCommand->Step();
712                 transaction.commit();
713                 return CKM_API_SUCCESS;
714             }
715             else
716             {
717                 LogError("Error: no such alias: " << alias);
718                 return CKM_API_ERROR_DB_ALIAS_UNKNOWN;
719             }
720         } Catch (SqlConnection::Exception::SyntaxError) {
721             LogError("Couldn't prepare delete statement");
722         } Catch (SqlConnection::Exception::InternalError) {
723             LogError("Couldn't execute delete statement");
724         }
725         ThrowMsg(DBCrypto::Exception::InternalError,
726                 "Couldn't delete permissions for alias " << alias << " using client label " << clnt_label);
727     }
728
729 } // CKM
730
731 #pragma GCC diagnostic pop